1 /* 2 * Copyright 2006-2010, 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 * Hugo Santos, hugosantos@gmail.com 8 */ 9 10 11 #include <net/if.h> 12 #include <net/if_dl.h> 13 #include <net/if_media.h> 14 #include <net/route.h> 15 #include <new> 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <sys/sockio.h> 20 21 #include <ByteOrder.h> 22 #include <KernelExport.h> 23 24 #include <net_datalink.h> 25 #include <net_device.h> 26 #include <NetBufferUtilities.h> 27 #include <NetUtilities.h> 28 29 #include "device_interfaces.h" 30 #include "domains.h" 31 #include "ethernet.h" 32 #include "interfaces.h" 33 #include "routes.h" 34 #include "stack_private.h" 35 #include "utility.h" 36 37 38 //#define TRACE_DATALINK 39 #ifdef TRACE_DATALINK 40 # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x) 41 #else 42 # define TRACE(x...) ; 43 #endif 44 45 46 struct datalink_protocol : net_protocol { 47 struct net_domain_private* domain; 48 }; 49 50 struct interface_protocol : net_datalink_protocol { 51 struct net_device_module_info* device_module; 52 struct net_device* device; 53 }; 54 55 56 #ifdef TRACE_DATALINK 57 58 59 static const char* 60 option_to_string(int32 option) 61 { 62 # define CODE(x) case x: return #x; 63 switch (option) { 64 CODE(SIOCADDRT) /* add route */ 65 CODE(SIOCDELRT) /* delete route */ 66 CODE(SIOCSIFADDR) /* set interface address */ 67 CODE(SIOCGIFADDR) /* get interface address */ 68 CODE(SIOCSIFDSTADDR) /* set point-to-point address */ 69 CODE(SIOCGIFDSTADDR) /* get point-to-point address */ 70 CODE(SIOCSIFFLAGS) /* set interface flags */ 71 CODE(SIOCGIFFLAGS) /* get interface flags */ 72 CODE(SIOCGIFBRDADDR) /* get broadcast address */ 73 CODE(SIOCSIFBRDADDR) /* set broadcast address */ 74 CODE(SIOCGIFCOUNT) /* count interfaces */ 75 CODE(SIOCGIFCONF) /* get interface list */ 76 CODE(SIOCGIFINDEX) /* interface name -> index */ 77 CODE(SIOCGIFNAME) /* interface index -> name */ 78 CODE(SIOCGIFNETMASK) /* get net address mask */ 79 CODE(SIOCSIFNETMASK) /* set net address mask */ 80 CODE(SIOCGIFMETRIC) /* get interface metric */ 81 CODE(SIOCSIFMETRIC) /* set interface metric */ 82 CODE(SIOCDIFADDR) /* delete interface address */ 83 CODE(SIOCAIFADDR) /* configure interface alias */ 84 CODE(SIOCADDMULTI) /* add multicast address */ 85 CODE(SIOCDELMULTI) /* delete multicast address */ 86 CODE(SIOCGIFMTU) /* get interface MTU */ 87 CODE(SIOCSIFMTU) /* set interface MTU */ 88 CODE(SIOCSIFMEDIA) /* set net media */ 89 CODE(SIOCGIFMEDIA) /* get net media */ 90 91 CODE(SIOCGRTSIZE) /* get route table size */ 92 CODE(SIOCGRTTABLE) /* get route table */ 93 CODE(SIOCGETRT) /* get route information for destination */ 94 95 CODE(SIOCGIFSTATS) /* get interface stats */ 96 CODE(SIOCGIFTYPE) /* get interface type */ 97 98 CODE(SIOCSPACKETCAP) /* Start capturing packets on an interface */ 99 CODE(SIOCCPACKETCAP) /* Stop capturing packets on an interface */ 100 101 CODE(SIOCSHIWAT) /* set high watermark */ 102 CODE(SIOCGHIWAT) /* get high watermark */ 103 CODE(SIOCSLOWAT) /* set low watermark */ 104 CODE(SIOCGLOWAT) /* get low watermark */ 105 CODE(SIOCATMARK) /* at out-of-band mark? */ 106 CODE(SIOCSPGRP) /* set process group */ 107 CODE(SIOCGPGRP) /* get process group */ 108 109 CODE(SIOCGPRIVATE_0) /* device private 0 */ 110 CODE(SIOCGPRIVATE_1) /* device private 1 */ 111 CODE(SIOCSDRVSPEC) /* set driver-specific parameters */ 112 CODE(SIOCGDRVSPEC) /* get driver-specific parameters */ 113 114 CODE(SIOCSIFGENERIC) /* generic IF set op */ 115 CODE(SIOCGIFGENERIC) /* generic IF get op */ 116 117 CODE(B_SOCKET_SET_ALIAS) /* set interface alias, ifaliasreq */ 118 CODE(B_SOCKET_GET_ALIAS) /* get interface alias, ifaliasreq */ 119 CODE(B_SOCKET_COUNT_ALIASES) /* count interface aliases */ 120 121 default: 122 static char buffer[24]; 123 snprintf(buffer, sizeof(buffer), "%" B_PRId32, option); 124 return buffer; 125 } 126 # undef CODE 127 } 128 129 130 #endif // TRACE_DATALINK 131 132 133 static status_t 134 get_interface_name_or_index(net_domain* domain, int32 option, void* value, 135 size_t* _length) 136 { 137 ASSERT(option == SIOCGIFINDEX || option == SIOCGIFNAME); 138 139 size_t expected = option == SIOCGIFINDEX ? IF_NAMESIZE : sizeof(ifreq); 140 if (*_length > 0 && *_length < expected) 141 return B_BAD_VALUE; 142 143 ifreq request; 144 memset(&request, 0, sizeof(request)); 145 146 if (user_memcpy(&request, value, expected) < B_OK) 147 return B_BAD_ADDRESS; 148 149 Interface* interface = NULL; 150 if (option == SIOCGIFINDEX) 151 interface = get_interface(domain, request.ifr_name); 152 else 153 interface = get_interface(domain, request.ifr_index); 154 155 if (interface == NULL) 156 return B_BAD_VALUE; 157 158 if (option == SIOCGIFINDEX) 159 request.ifr_index = interface->index; 160 else 161 strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); 162 163 *_length = sizeof(ifreq); 164 interface->ReleaseReference(); 165 166 return user_memcpy(value, &request, sizeof(ifreq)); 167 } 168 169 170 static void 171 set_interface_address(net_interface_address*& target, InterfaceAddress* address) 172 { 173 if (target != NULL) 174 static_cast<InterfaceAddress*>(target)->ReleaseReference(); 175 176 target = address; 177 } 178 179 180 static status_t 181 fill_address(const sockaddr* from, sockaddr* to, size_t maxLength) 182 { 183 if (from != NULL) { 184 // Copy address over 185 return user_memcpy(to, from, min_c(from->sa_len, maxLength)); 186 } 187 188 // Fill in empty address 189 sockaddr empty; 190 empty.sa_len = 2; 191 empty.sa_family = AF_UNSPEC; 192 193 return user_memcpy(to, &empty, min_c(2, maxLength)); 194 } 195 196 197 // #pragma mark - datalink module 198 199 200 static status_t 201 datalink_control(net_domain* _domain, int32 option, void* value, 202 size_t* _length) 203 { 204 TRACE("%s(domain %p, option %s, value %p, length %zu)\n", __FUNCTION__, 205 _domain, option_to_string(option), value, *_length); 206 207 net_domain_private* domain = (net_domain_private*)_domain; 208 if (domain == NULL || domain->family == AF_LINK) { 209 // the AF_LINK family is already handled completely in the link protocol 210 return B_BAD_VALUE; 211 } 212 213 switch (option) { 214 case SIOCGIFINDEX: 215 case SIOCGIFNAME: 216 return get_interface_name_or_index(domain, option, value, _length); 217 218 case SIOCAIFADDR: /* same as B_SOCKET_ADD_ALIAS */ 219 { 220 // add new interface address 221 if (*_length > 0 && *_length < sizeof(struct ifaliasreq)) 222 return B_BAD_VALUE; 223 224 struct ifaliasreq request; 225 if (user_memcpy(&request, value, sizeof(struct ifaliasreq)) != B_OK) 226 return B_BAD_ADDRESS; 227 228 Interface* interface = get_interface(domain, request.ifra_name); 229 if (interface != NULL) { 230 // A new alias is added to this interface 231 status_t status = add_interface_address(interface, domain, 232 request); 233 notify_interface_changed(interface); 234 interface->ReleaseReference(); 235 236 return status; 237 } 238 239 // A new interface needs to be added 240 net_device_interface* deviceInterface 241 = get_device_interface(request.ifra_name); 242 if (deviceInterface == NULL) 243 return B_DEVICE_NOT_FOUND; 244 245 status_t status = add_interface(request.ifra_name, domain, request, 246 deviceInterface); 247 248 put_device_interface(deviceInterface); 249 return status; 250 } 251 252 case SIOCDIFADDR: /* same as B_SOCKET_REMOVE_ALIAS */ 253 { 254 // remove interface (address) 255 struct ifreq request; 256 if (user_memcpy(&request, value, sizeof(struct ifreq)) != B_OK) 257 return B_BAD_ADDRESS; 258 259 Interface* interface = get_interface(domain, request.ifr_name); 260 if (interface == NULL) 261 return B_BAD_VALUE; 262 263 status_t status = B_OK; 264 265 if (request.ifr_addr.sa_family != AF_UNSPEC 266 && request.ifr_addr.sa_len != 0) { 267 status = interface->Control(domain, SIOCDIFADDR, request, 268 (ifreq*)value, *_length); 269 } else 270 remove_interface(interface); 271 272 interface->ReleaseReference(); 273 274 return status; 275 } 276 277 case SIOCGIFCOUNT: 278 { 279 // count number of interfaces 280 struct ifconf config; 281 config.ifc_value = count_interfaces(); 282 283 return user_memcpy(value, &config, sizeof(struct ifconf)); 284 } 285 286 case SIOCGIFCONF: 287 { 288 // retrieve ifreqs for all interfaces 289 struct ifconf config; 290 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) 291 return B_BAD_ADDRESS; 292 293 size_t size = config.ifc_len; 294 status_t status 295 = list_interfaces(domain->family, config.ifc_buf, &size); 296 if (status != B_OK) 297 return status; 298 299 config.ifc_len = (int)size; 300 return user_memcpy(value, &config, sizeof(struct ifconf)); 301 } 302 303 case SIOCGRTSIZE: 304 { 305 // determine size of buffer to hold the routing table 306 struct ifconf config; 307 config.ifc_value = route_table_size(domain); 308 309 return user_memcpy(value, &config, sizeof(struct ifconf)); 310 } 311 case SIOCGRTTABLE: 312 { 313 // retrieve all routes for this domain 314 struct ifconf config; 315 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) 316 return B_BAD_ADDRESS; 317 318 return list_routes(domain, config.ifc_buf, config.ifc_len); 319 } 320 case SIOCGETRT: 321 return get_route_information(domain, value, *_length); 322 323 default: 324 { 325 // We also accept partial ifreqs as long as the name is complete. 326 size_t length = sizeof(struct ifreq); 327 if (*_length > 0 && *_length >= IF_NAMESIZE) 328 length = min_c(length, *_length); 329 330 // try to pass the request to an existing interface 331 struct ifreq request; 332 if (user_memcpy(&request, value, length) != B_OK) 333 return B_BAD_ADDRESS; 334 335 Interface* interface = get_interface(domain, request.ifr_name); 336 if (interface == NULL) 337 return B_BAD_VALUE; 338 339 status_t status = interface->Control(domain, option, request, 340 (ifreq*)value, *_length); 341 342 interface->ReleaseReference(); 343 return status; 344 } 345 } 346 return B_BAD_VALUE; 347 } 348 349 350 static status_t 351 datalink_send_routed_data(struct net_route* route, net_buffer* buffer) 352 { 353 TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer); 354 355 InterfaceAddress* address = (InterfaceAddress*)route->interface_address; 356 Interface* interface = (Interface*)address->interface; 357 358 //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n", 359 // buffer->size, interface->name, route->flags); 360 361 if ((route->flags & RTF_REJECT) != 0) { 362 TRACE(" rejected route\n"); 363 return ENETUNREACH; 364 } 365 366 if ((route->flags & RTF_HOST) != 0) { 367 TRACE(" host route\n"); 368 // We set the interface address here, so the buffer is delivered 369 // directly to the domain in interfaces.cpp:device_consumer_thread() 370 address->AcquireReference(); 371 set_interface_address(buffer->interface_address, address); 372 } 373 374 if ((route->flags & RTF_LOCAL) != 0) { 375 TRACE(" local route\n"); 376 377 // We set the interface address here, so the buffer is delivered 378 // directly to the domain in interfaces.cpp:device_consumer_thread() 379 address->AcquireReference(); 380 set_interface_address(buffer->interface_address, address); 381 382 if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) { 383 { 384 NetBufferPrepend<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer); 385 if (bufferHeader.Status() != B_OK) 386 return bufferHeader.Status(); 387 388 ether_header &header = bufferHeader.Data(); 389 switch (buffer->interface_address->domain->family) { 390 case AF_INET: 391 header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IP); 392 break; 393 case AF_INET6: 394 header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IPV6); 395 break; 396 default: 397 header.type = 0; 398 break; 399 } 400 401 memset(header.source, 0, ETHER_ADDRESS_LENGTH); 402 memset(header.destination, 0, ETHER_ADDRESS_LENGTH); 403 bufferHeader.Sync(); 404 } 405 device_interface_monitor_receive(interface->DeviceInterface(), buffer); 406 { 407 NetBufferHeaderRemover<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer); 408 if (bufferHeader.Status() != B_OK) 409 return bufferHeader.Status(); 410 } 411 } 412 413 // this one goes back to the domain directly 414 return fifo_enqueue_buffer( 415 &interface->DeviceInterface()->receive_queue, buffer); 416 } 417 418 if ((route->flags & RTF_GATEWAY) != 0) { 419 TRACE(" gateway route\n"); 420 421 // This route involves a gateway, we need to use the gateway address 422 // instead of the destination address: 423 if (route->gateway == NULL) 424 return B_MISMATCHED_VALUES; 425 memcpy(buffer->destination, route->gateway, route->gateway->sa_len); 426 } 427 428 // this goes out to the datalink protocols 429 domain_datalink* datalink 430 = interface->DomainDatalink(address->domain->family); 431 return datalink->first_info->send_data(datalink->first_protocol, buffer); 432 } 433 434 435 /*! Finds a route for the given \a buffer in the given \a domain, and calls 436 net_protocol_info::send_routed_data() on either the \a protocol (if 437 non-NULL), or the domain. 438 */ 439 static status_t 440 datalink_send_data(net_protocol* protocol, net_domain* domain, 441 net_buffer* buffer) 442 { 443 TRACE("%s(%p, domain %p, buffer %p)\n", __FUNCTION__, protocol, domain, 444 buffer); 445 446 if (protocol == NULL && domain == NULL) 447 return B_BAD_VALUE; 448 449 net_protocol_module_info* module = protocol != NULL 450 ? protocol->module : domain->module; 451 452 if (domain == NULL) 453 domain = protocol->module->get_domain(protocol); 454 455 net_route* route = NULL; 456 status_t status; 457 if (protocol != NULL && protocol->socket != NULL 458 && protocol->socket->bound_to_device != 0) { 459 status = get_device_route(domain, protocol->socket->bound_to_device, 460 &route); 461 } else 462 status = get_buffer_route(domain, buffer, &route); 463 464 TRACE(" route status: %s\n", strerror(status)); 465 466 if (status != B_OK) 467 return status; 468 469 status = module->send_routed_data(protocol, route, buffer); 470 put_route(domain, route); 471 return status; 472 } 473 474 475 /*! Tests if \a address is a local address in the domain. 476 477 \param _interfaceAddress will be set to the interface address belonging to 478 that address if non-NULL. If the address \a _interfaceAddress points to 479 is not NULL, it is assumed that it already points to an address, which 480 is then released before the new address is assigned. 481 \param _matchedType will be set to either zero or MSG_BCAST if non-NULL. 482 */ 483 static bool 484 datalink_is_local_address(net_domain* domain, const struct sockaddr* address, 485 net_interface_address** _interfaceAddress, uint32* _matchedType) 486 { 487 TRACE("%s(domain %p, address %s)\n", __FUNCTION__, domain, 488 AddressString(domain, address).Data()); 489 490 if (domain == NULL || address == NULL 491 || domain->family != address->sa_family) 492 return false; 493 494 uint32 matchedType = 0; 495 496 InterfaceAddress* interfaceAddress = get_interface_address(address); 497 if (interfaceAddress == NULL) { 498 // Check for matching broadcast address 499 if ((domain->address_module->flags 500 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 501 interfaceAddress 502 = get_interface_address_for_destination(domain, address); 503 matchedType = MSG_BCAST; 504 } 505 if (interfaceAddress == NULL) { 506 TRACE(" no\n"); 507 return false; 508 } 509 } 510 511 TRACE(" it is, interface address %p\n", interfaceAddress); 512 513 if (_interfaceAddress != NULL) 514 set_interface_address(*_interfaceAddress, interfaceAddress); 515 else 516 interfaceAddress->ReleaseReference(); 517 518 if (_matchedType != NULL) 519 *_matchedType = matchedType; 520 521 return true; 522 } 523 524 525 /*! Tests if \a address is a local link address in the domain. 526 527 \param unconfiguredOnly only unconfigured interfaces are taken into account. 528 \param _interfaceAddress will be set to the first address of the interface 529 and domain belonging to that address if non-NULL. If the address 530 \a _interfaceAddress points to is not NULL, it is assumed that it 531 already points to an address, which is then released before the new 532 address is assigned. 533 */ 534 static bool 535 datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly, 536 const struct sockaddr* address, net_interface_address** _interfaceAddress) 537 { 538 if (domain == NULL || address == NULL || address->sa_family != AF_LINK) 539 return false; 540 541 #ifdef TRACE_DATALINK 542 uint8* data = LLADDR((sockaddr_dl*)address); 543 TRACE("%s(domain %p, unconfiguredOnly %d, address %02x:%02x:%02x:%02x:%02x" 544 ":%02x)\n", __FUNCTION__, domain, unconfiguredOnly, data[0], data[1], 545 data[2], data[3], data[4], data[5]); 546 #endif 547 548 InterfaceAddress* interfaceAddress = get_interface_address_for_link(domain, 549 address, unconfiguredOnly); 550 if (interfaceAddress == NULL) { 551 TRACE(" no\n"); 552 return false; 553 } 554 555 if (_interfaceAddress != NULL) 556 set_interface_address(*_interfaceAddress, interfaceAddress); 557 else 558 interfaceAddress->ReleaseReference(); 559 560 return true; 561 } 562 563 564 static net_interface* 565 datalink_get_interface(net_domain* domain, uint32 index) 566 { 567 return get_interface(domain, index); 568 } 569 570 571 static net_interface* 572 datalink_get_interface_with_address(const sockaddr* address) 573 { 574 InterfaceAddress* interfaceAddress = get_interface_address(address); 575 if (interfaceAddress == NULL) 576 return NULL; 577 578 Interface* interface = static_cast<Interface*>(interfaceAddress->interface); 579 580 interface->AcquireReference(); 581 interfaceAddress->ReleaseReference(); 582 583 return interface; 584 } 585 586 587 static void 588 datalink_put_interface(net_interface* interface) 589 { 590 if (interface == NULL) 591 return; 592 593 ((Interface*)interface)->ReleaseReference(); 594 } 595 596 597 static net_interface_address* 598 datalink_get_interface_address(const struct sockaddr* address) 599 { 600 return get_interface_address(address); 601 } 602 603 604 /*! Returns a reference to the next address of the given interface in 605 \a _address. When you call this function the first time, \a _address must 606 point to a NULL address. Upon the next call, the reference to the previous 607 address is taken over again. 608 609 If you do not traverse the list to the end, you'll have to manually release 610 the reference to the address where you stopped. 611 612 \param interface The interface whose address list should be iterated over. 613 \param _address A pointer to the location where the next address should 614 be stored. 615 616 \return \c true if an address reference was returned, \c false if not. 617 */ 618 static bool 619 datalink_get_next_interface_address(net_interface* _interface, 620 net_interface_address** _address) 621 { 622 Interface* interface = (Interface*)_interface; 623 624 InterfaceAddress* address = (InterfaceAddress*)*_address; 625 bool gotOne = interface->GetNextAddress(&address); 626 *_address = address; 627 628 return gotOne; 629 } 630 631 632 static void 633 datalink_put_interface_address(net_interface_address* address) 634 { 635 if (address == NULL) 636 return; 637 638 ((InterfaceAddress*)address)->ReleaseReference(); 639 } 640 641 642 static status_t 643 datalink_join_multicast(net_interface* _interface, net_domain* domain, 644 const struct sockaddr* address) 645 { 646 Interface* interface = (Interface*)_interface; 647 domain_datalink* datalink = interface->DomainDatalink(domain->family); 648 649 return datalink->first_info->join_multicast(datalink->first_protocol, 650 address); 651 } 652 653 654 static status_t 655 datalink_leave_multicast(net_interface* _interface, net_domain* domain, 656 const struct sockaddr* address) 657 { 658 Interface* interface = (Interface*)_interface; 659 domain_datalink* datalink = interface->DomainDatalink(domain->family); 660 661 return datalink->first_info->leave_multicast(datalink->first_protocol, 662 address); 663 } 664 665 666 static status_t 667 datalink_std_ops(int32 op, ...) 668 { 669 switch (op) { 670 case B_MODULE_INIT: 671 case B_MODULE_UNINIT: 672 return B_OK; 673 674 default: 675 return B_ERROR; 676 } 677 } 678 679 680 // #pragma mark - net_datalink_protocol 681 682 683 static status_t 684 interface_protocol_init(net_interface* interface, net_domain* domain, 685 net_datalink_protocol** _protocol) 686 { 687 interface_protocol* protocol = new(std::nothrow) interface_protocol; 688 if (protocol == NULL) 689 return B_NO_MEMORY; 690 691 TRACE("%s(%p, interface %p - %s, domain %p)\n", __FUNCTION__, protocol, 692 interface, interface->name, domain); 693 694 protocol->device_module = interface->device->module; 695 protocol->device = interface->device; 696 697 *_protocol = protocol; 698 return B_OK; 699 } 700 701 702 static status_t 703 interface_protocol_uninit(net_datalink_protocol* protocol) 704 { 705 TRACE("%s(%p)\n", __FUNCTION__, protocol); 706 707 delete protocol; 708 return B_OK; 709 } 710 711 712 static status_t 713 interface_protocol_send_data(net_datalink_protocol* _protocol, 714 net_buffer* buffer) 715 { 716 TRACE("%s(%p, buffer %p)\n", __FUNCTION__, _protocol, buffer); 717 718 interface_protocol* protocol = (interface_protocol*)_protocol; 719 Interface* interface = (Interface*)protocol->interface; 720 721 if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) 722 device_interface_monitor_receive(interface->DeviceInterface(), buffer); 723 724 return protocol->device_module->send_data(protocol->device, buffer); 725 } 726 727 728 static status_t 729 interface_protocol_up(net_datalink_protocol* protocol) 730 { 731 TRACE("%s(%p)\n", __FUNCTION__, protocol); 732 return B_OK; 733 } 734 735 736 static void 737 interface_protocol_down(net_datalink_protocol* _protocol) 738 { 739 TRACE("%s(%p)\n", __FUNCTION__, _protocol); 740 741 interface_protocol* protocol = (interface_protocol*)_protocol; 742 Interface* interface = (Interface*)protocol->interface; 743 net_device_interface* deviceInterface = interface->DeviceInterface(); 744 745 if (deviceInterface->up_count == 0) 746 return; 747 748 deviceInterface->up_count--; 749 750 interface->WentDown(); 751 752 if (deviceInterface->up_count > 0) 753 return; 754 755 down_device_interface(deviceInterface); 756 } 757 758 759 static status_t 760 interface_protocol_change_address(net_datalink_protocol* protocol, 761 net_interface_address* interfaceAddress, int32 option, 762 const struct sockaddr* oldAddress, const struct sockaddr* newAddress) 763 { 764 TRACE("%s(%p, interface address %p, option %s, old %p, new %p)\n", 765 __FUNCTION__, protocol, interfaceAddress, option_to_string(option), 766 oldAddress, newAddress); 767 768 switch (option) { 769 case SIOCSIFADDR: 770 case SIOCSIFNETMASK: 771 case SIOCSIFBRDADDR: 772 case SIOCSIFDSTADDR: 773 case SIOCDIFADDR: 774 return update_interface_address((InterfaceAddress*)interfaceAddress, 775 option, oldAddress, newAddress); 776 } 777 778 return B_OK; 779 } 780 781 782 static status_t 783 interface_protocol_control(net_datalink_protocol* _protocol, int32 option, 784 void* argument, size_t length) 785 { 786 TRACE("%s(%p, option %s, argument %p, length %zu)\n", __FUNCTION__, 787 _protocol, option_to_string(option), argument, length); 788 789 interface_protocol* protocol = (interface_protocol*)_protocol; 790 Interface* interface = (Interface*)protocol->interface; 791 792 switch (option) { 793 case SIOCGIFADDR: 794 case SIOCGIFNETMASK: 795 case SIOCGIFBRDADDR: 796 case SIOCGIFDSTADDR: 797 { 798 if (length == 0) 799 length = sizeof(ifreq); 800 else if (length < sizeof(ifreq)) 801 return B_BAD_VALUE; 802 803 ifreq request; 804 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) 805 return B_BAD_ADDRESS; 806 807 InterfaceAddress* interfaceAddress 808 = get_interface_address(&request.ifr_addr); 809 if (interfaceAddress == NULL) { 810 interfaceAddress 811 = interface->FirstForFamily(protocol->domain->family); 812 if (interfaceAddress == NULL) 813 return B_BAD_VALUE; 814 } 815 816 size_t maxLength = length - offsetof(ifreq, ifr_addr); 817 818 status_t status = fill_address( 819 *interfaceAddress->AddressFor(option), 820 &((struct ifreq*)argument)->ifr_addr, maxLength); 821 822 interfaceAddress->ReleaseReference(); 823 return status; 824 } 825 826 case B_SOCKET_COUNT_ALIASES: 827 { 828 ifreq request; 829 request.ifr_count = interface->CountAddresses(); 830 831 return user_memcpy(&((struct ifreq*)argument)->ifr_count, 832 &request.ifr_count, sizeof(request.ifr_count)); 833 } 834 835 case B_SOCKET_GET_ALIAS: 836 { 837 ifaliasreq request; 838 if (user_memcpy(&request, argument, sizeof(ifaliasreq)) != B_OK) 839 return B_BAD_ADDRESS; 840 841 InterfaceAddress* address = NULL; 842 if (request.ifra_index < 0) { 843 if (!protocol->domain->address_module->is_empty_address( 844 (const sockaddr*)&request.ifra_addr, false)) { 845 // Find first address that matches the local address 846 address = interface->AddressForLocal(protocol->domain, 847 (const sockaddr*)&request.ifra_addr); 848 } else { 849 // Find first address for family 850 address = interface->FirstForFamily( 851 protocol->domain->family); 852 } 853 854 request.ifra_index = interface->IndexOfAddress(address); 855 } else 856 address = interface->AddressAt(request.ifra_index); 857 if (address == NULL) 858 return B_BAD_VALUE; 859 860 // Copy index (in case none was specified) 861 status_t status = user_memcpy( 862 &((struct ifaliasreq*)argument)->ifra_index, 863 &request.ifra_index, sizeof(request.ifra_index)); 864 865 // Copy address info 866 if (status == B_OK) { 867 status = fill_address(address->local, 868 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_addr, 869 sizeof(sockaddr_storage)); 870 } 871 if (status == B_OK) { 872 status = fill_address(address->mask, 873 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_mask, 874 sizeof(sockaddr_storage)); 875 } 876 if (status == B_OK) { 877 status = fill_address(address->destination, 878 (sockaddr*)&((struct ifaliasreq*)argument) 879 ->ifra_destination, 880 sizeof(sockaddr_storage)); 881 } 882 883 address->ReleaseReference(); 884 885 return status; 886 } 887 888 case SIOCGIFFLAGS: 889 { 890 // get flags 891 struct ifreq request; 892 request.ifr_flags = interface->flags | interface->device->flags; 893 894 return user_memcpy(&((struct ifreq*)argument)->ifr_flags, 895 &request.ifr_flags, sizeof(request.ifr_flags)); 896 } 897 898 case SIOCGIFSTATS: 899 { 900 // get stats 901 return user_memcpy(&((struct ifreq*)argument)->ifr_stats, 902 &interface->DeviceInterface()->device->stats, 903 sizeof(struct ifreq_stats)); 904 } 905 906 case SIOCGIFTYPE: 907 { 908 // get type 909 struct ifreq request; 910 request.ifr_type = interface->type; 911 912 return user_memcpy(&((struct ifreq*)argument)->ifr_type, 913 &request.ifr_type, sizeof(request.ifr_type)); 914 } 915 916 case SIOCGIFMTU: 917 { 918 // get MTU 919 struct ifreq request; 920 request.ifr_mtu = interface->device->mtu; 921 922 return user_memcpy(&((struct ifreq*)argument)->ifr_mtu, 923 &request.ifr_mtu, sizeof(request.ifr_mtu)); 924 } 925 case SIOCSIFMTU: 926 { 927 // set MTU 928 struct ifreq request; 929 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) 930 return B_BAD_ADDRESS; 931 932 status_t status = interface->device->module->set_mtu( 933 interface->device, request.ifr_mtu); 934 if (status == B_OK) 935 notify_interface_changed(interface); 936 return status; 937 } 938 939 case SIOCSIFMEDIA: 940 { 941 // set media 942 struct ifreq request; 943 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) 944 return B_BAD_ADDRESS; 945 946 status_t status 947 = interface->device->module->set_media( 948 interface->device, request.ifr_media); 949 if (status == B_NOT_SUPPORTED) { 950 // TODO: this isn't so nice, and should be solved differently 951 // (for example by removing the set_media() call altogether, or 952 // making it able to deal properly with FreeBSD drivers as well) 953 // try driver directly 954 status = interface->device->module->control( 955 interface->device, SIOCSIFMEDIA, &request, sizeof(request)); 956 } 957 958 return status; 959 } 960 case SIOCGIFMEDIA: 961 { 962 // get media 963 const size_t copylen = offsetof(ifreq, ifr_media) + sizeof(ifreq::ifr_media); 964 if (length > 0 && length < copylen) 965 return B_BAD_VALUE; 966 967 struct ifreq request; 968 if (user_memcpy(&request, argument, copylen) != B_OK) 969 return B_BAD_ADDRESS; 970 971 request.ifr_media = interface->device->media; 972 return user_memcpy(argument, &request, copylen); 973 } 974 975 case SIOCGIFMETRIC: 976 { 977 // get metric 978 struct ifreq request; 979 request.ifr_metric = interface->metric; 980 981 return user_memcpy(&((struct ifreq*)argument)->ifr_metric, 982 &request.ifr_metric, sizeof(request.ifr_metric)); 983 } 984 case SIOCSIFMETRIC: 985 { 986 // set metric 987 struct ifreq request; 988 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 989 return B_BAD_ADDRESS; 990 991 interface->metric = request.ifr_metric; 992 notify_interface_changed(interface); 993 return B_OK; 994 } 995 996 case SIOCADDRT: 997 case SIOCDELRT: 998 // interface related route options 999 return control_routes(interface, protocol->domain, option, argument, 1000 length); 1001 } 1002 1003 return protocol->device_module->control(protocol->device, 1004 option, argument, length); 1005 } 1006 1007 1008 static status_t 1009 interface_protocol_join_multicast(net_datalink_protocol* _protocol, 1010 const sockaddr* address) 1011 { 1012 interface_protocol* protocol = (interface_protocol*)_protocol; 1013 1014 return protocol->device_module->add_multicast(protocol->device, address); 1015 } 1016 1017 1018 static status_t 1019 interface_protocol_leave_multicast(net_datalink_protocol* _protocol, 1020 const sockaddr* address) 1021 { 1022 interface_protocol* protocol = (interface_protocol*)_protocol; 1023 1024 return protocol->device_module->remove_multicast(protocol->device, 1025 address); 1026 } 1027 1028 1029 net_datalink_module_info gNetDatalinkModule = { 1030 { 1031 NET_DATALINK_MODULE_NAME, 1032 0, 1033 datalink_std_ops 1034 }, 1035 1036 datalink_control, 1037 datalink_send_routed_data, 1038 datalink_send_data, 1039 1040 datalink_is_local_address, 1041 datalink_is_local_link_address, 1042 1043 datalink_get_interface, 1044 datalink_get_interface_with_address, 1045 datalink_put_interface, 1046 1047 datalink_get_interface_address, 1048 datalink_get_next_interface_address, 1049 datalink_put_interface_address, 1050 1051 datalink_join_multicast, 1052 datalink_leave_multicast, 1053 1054 add_route, 1055 remove_route, 1056 get_route, 1057 get_buffer_route, 1058 put_route, 1059 register_route_info, 1060 unregister_route_info, 1061 update_route_info 1062 }; 1063 1064 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = { 1065 { 1066 NULL, 1067 0, 1068 NULL 1069 }, 1070 interface_protocol_init, 1071 interface_protocol_uninit, 1072 interface_protocol_send_data, 1073 interface_protocol_up, 1074 interface_protocol_down, 1075 interface_protocol_change_address, 1076 interface_protocol_control, 1077 interface_protocol_join_multicast, 1078 interface_protocol_leave_multicast, 1079 }; 1080