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