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 < 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 < 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 if (*_length < IF_NAMESIZE) 324 return B_BAD_VALUE; 325 326 size_t length = min_c(sizeof(struct ifreq), *_length); 327 328 // try to pass the request to an existing interface 329 struct ifreq request; 330 if (user_memcpy(&request, value, length) != B_OK) 331 return B_BAD_ADDRESS; 332 333 Interface* interface = get_interface(domain, request.ifr_name); 334 if (interface == NULL) 335 return B_BAD_VALUE; 336 337 status_t status = interface->Control(domain, option, request, 338 (ifreq*)value, *_length); 339 340 interface->ReleaseReference(); 341 return status; 342 } 343 } 344 return B_BAD_VALUE; 345 } 346 347 348 static status_t 349 datalink_send_routed_data(struct net_route* route, net_buffer* buffer) 350 { 351 TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer); 352 353 InterfaceAddress* address = (InterfaceAddress*)route->interface_address; 354 Interface* interface = (Interface*)address->interface; 355 356 //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n", 357 // buffer->size, interface->name, route->flags); 358 359 if ((route->flags & RTF_REJECT) != 0) { 360 TRACE(" rejected route\n"); 361 return ENETUNREACH; 362 } 363 364 if ((route->flags & RTF_LOCAL) != 0) { 365 TRACE(" local route\n"); 366 367 // We set the interface address here, so the buffer is delivered 368 // directly to the domain in interfaces.cpp:device_consumer_thread() 369 address->AcquireReference(); 370 set_interface_address(buffer->interface_address, address); 371 372 // this one goes back to the domain directly 373 return fifo_enqueue_buffer( 374 &interface->DeviceInterface()->receive_queue, buffer); 375 } 376 377 if ((route->flags & RTF_GATEWAY) != 0) { 378 TRACE(" gateway route\n"); 379 380 // This route involves a gateway, we need to use the gateway address 381 // instead of the destination address: 382 if (route->gateway == NULL) 383 return B_MISMATCHED_VALUES; 384 memcpy(buffer->destination, route->gateway, route->gateway->sa_len); 385 } 386 387 // this goes out to the datalink protocols 388 domain_datalink* datalink 389 = interface->DomainDatalink(address->domain->family); 390 return datalink->first_info->send_data(datalink->first_protocol, buffer); 391 } 392 393 394 /*! Finds a route for the given \a buffer in the given \a domain, and calls 395 net_protocol_info::send_routed_data() on either the \a protocol (if 396 non-NULL), or the domain. 397 */ 398 static status_t 399 datalink_send_data(net_protocol* protocol, net_domain* domain, 400 net_buffer* buffer) 401 { 402 TRACE("%s(%p, domain %p, buffer %p)\n", __FUNCTION__, protocol, domain, 403 buffer); 404 405 if (protocol == NULL && domain == NULL) 406 return B_BAD_VALUE; 407 408 net_protocol_module_info* module = protocol != NULL 409 ? protocol->module : domain->module; 410 411 if (domain == NULL) 412 domain = protocol->module->get_domain(protocol); 413 414 net_route* route = NULL; 415 status_t status; 416 if (protocol != NULL && protocol->socket != NULL 417 && protocol->socket->bound_to_device != 0) { 418 status = get_device_route(domain, protocol->socket->bound_to_device, 419 &route); 420 } else 421 status = get_buffer_route(domain, buffer, &route); 422 423 TRACE(" route status: %s\n", strerror(status)); 424 425 if (status != B_OK) 426 return status; 427 428 status = module->send_routed_data(protocol, route, buffer); 429 put_route(domain, route); 430 return status; 431 } 432 433 434 /*! Tests if \a address is a local address in the domain. 435 436 \param _interfaceAddress will be set to the interface address belonging to 437 that address if non-NULL. If the address \a _interfaceAddress points to 438 is not NULL, it is assumed that it already points to an address, which 439 is then released before the new address is assigned. 440 \param _matchedType will be set to either zero or MSG_BCAST if non-NULL. 441 */ 442 static bool 443 datalink_is_local_address(net_domain* domain, const struct sockaddr* address, 444 net_interface_address** _interfaceAddress, uint32* _matchedType) 445 { 446 TRACE("%s(domain %p, address %s)\n", __FUNCTION__, domain, 447 AddressString(domain, address).Data()); 448 449 if (domain == NULL || address == NULL 450 || domain->family != address->sa_family) 451 return false; 452 453 uint32 matchedType = 0; 454 455 InterfaceAddress* interfaceAddress = get_interface_address(address); 456 if (interfaceAddress == NULL) { 457 // Check for matching broadcast address 458 if ((domain->address_module->flags 459 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) { 460 interfaceAddress 461 = get_interface_address_for_destination(domain, address); 462 matchedType = MSG_BCAST; 463 } 464 if (interfaceAddress == NULL) { 465 TRACE(" no\n"); 466 return false; 467 } 468 } 469 470 TRACE(" it is, interface address %p\n", interfaceAddress); 471 472 if (_interfaceAddress != NULL) 473 set_interface_address(*_interfaceAddress, interfaceAddress); 474 else 475 interfaceAddress->ReleaseReference(); 476 477 if (_matchedType != NULL) 478 *_matchedType = matchedType; 479 480 return true; 481 } 482 483 484 /*! Tests if \a address is a local link address in the domain. 485 486 \param unconfiguredOnly only unconfigured interfaces are taken into account. 487 \param _interfaceAddress will be set to the first address of the interface 488 and domain belonging to that address if non-NULL. If the address 489 \a _interfaceAddress points to is not NULL, it is assumed that it 490 already points to an address, which is then released before the new 491 address is assigned. 492 */ 493 static bool 494 datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly, 495 const struct sockaddr* address, net_interface_address** _interfaceAddress) 496 { 497 if (domain == NULL || address == NULL || address->sa_family != AF_LINK) 498 return false; 499 500 #ifdef TRACE_DATALINK 501 uint8* data = LLADDR((sockaddr_dl*)address); 502 TRACE("%s(domain %p, unconfiguredOnly %d, address %02x:%02x:%02x:%02x:%02x" 503 ":%02x)\n", __FUNCTION__, domain, unconfiguredOnly, data[0], data[1], 504 data[2], data[3], data[4], data[5]); 505 #endif 506 507 InterfaceAddress* interfaceAddress = get_interface_address_for_link(domain, 508 address, unconfiguredOnly); 509 if (interfaceAddress == NULL) { 510 TRACE(" no\n"); 511 return false; 512 } 513 514 if (_interfaceAddress != NULL) 515 set_interface_address(*_interfaceAddress, interfaceAddress); 516 else 517 interfaceAddress->ReleaseReference(); 518 519 return true; 520 } 521 522 523 static net_interface* 524 datalink_get_interface(net_domain* domain, uint32 index) 525 { 526 return get_interface(domain, index); 527 } 528 529 530 static net_interface* 531 datalink_get_interface_with_address(const sockaddr* address) 532 { 533 InterfaceAddress* interfaceAddress = get_interface_address(address); 534 if (interfaceAddress == NULL) 535 return NULL; 536 537 Interface* interface = static_cast<Interface*>(interfaceAddress->interface); 538 539 interface->AcquireReference(); 540 interfaceAddress->ReleaseReference(); 541 542 return interface; 543 } 544 545 546 static void 547 datalink_put_interface(net_interface* interface) 548 { 549 if (interface == NULL) 550 return; 551 552 ((Interface*)interface)->ReleaseReference(); 553 } 554 555 556 static net_interface_address* 557 datalink_get_interface_address(const struct sockaddr* address) 558 { 559 return get_interface_address(address); 560 } 561 562 563 /*! Returns a reference to the next address of the given interface in 564 \a _address. When you call this function the first time, \a _address must 565 point to a NULL address. Upon the next call, the reference to the previous 566 address is taken over again. 567 568 If you do not traverse the list to the end, you'll have to manually release 569 the reference to the address where you stopped. 570 571 \param interface The interface whose address list should be iterated over. 572 \param _address A pointer to the location where the next address should 573 be stored. 574 575 \return \c true if an address reference was returned, \c false if not. 576 */ 577 static bool 578 datalink_get_next_interface_address(net_interface* _interface, 579 net_interface_address** _address) 580 { 581 Interface* interface = (Interface*)_interface; 582 583 InterfaceAddress* address = (InterfaceAddress*)*_address; 584 bool gotOne = interface->GetNextAddress(&address); 585 *_address = address; 586 587 return gotOne; 588 } 589 590 591 static void 592 datalink_put_interface_address(net_interface_address* address) 593 { 594 if (address == NULL) 595 return; 596 597 ((InterfaceAddress*)address)->ReleaseReference(); 598 } 599 600 601 static status_t 602 datalink_join_multicast(net_interface* _interface, net_domain* domain, 603 const struct sockaddr* address) 604 { 605 Interface* interface = (Interface*)_interface; 606 domain_datalink* datalink = interface->DomainDatalink(domain->family); 607 608 return datalink->first_info->join_multicast(datalink->first_protocol, 609 address); 610 } 611 612 613 static status_t 614 datalink_leave_multicast(net_interface* _interface, net_domain* domain, 615 const struct sockaddr* address) 616 { 617 Interface* interface = (Interface*)_interface; 618 domain_datalink* datalink = interface->DomainDatalink(domain->family); 619 620 return datalink->first_info->leave_multicast(datalink->first_protocol, 621 address); 622 } 623 624 625 static status_t 626 datalink_std_ops(int32 op, ...) 627 { 628 switch (op) { 629 case B_MODULE_INIT: 630 case B_MODULE_UNINIT: 631 return B_OK; 632 633 default: 634 return B_ERROR; 635 } 636 } 637 638 639 // #pragma mark - net_datalink_protocol 640 641 642 static status_t 643 interface_protocol_init(net_interface* interface, net_domain* domain, 644 net_datalink_protocol** _protocol) 645 { 646 interface_protocol* protocol = new(std::nothrow) interface_protocol; 647 if (protocol == NULL) 648 return B_NO_MEMORY; 649 650 TRACE("%s(%p, interface %p - %s, domain %p)\n", __FUNCTION__, protocol, 651 interface, interface->name, domain); 652 653 protocol->device_module = interface->device->module; 654 protocol->device = interface->device; 655 656 *_protocol = protocol; 657 return B_OK; 658 } 659 660 661 static status_t 662 interface_protocol_uninit(net_datalink_protocol* protocol) 663 { 664 TRACE("%s(%p)\n", __FUNCTION__, protocol); 665 666 delete protocol; 667 return B_OK; 668 } 669 670 671 static status_t 672 interface_protocol_send_data(net_datalink_protocol* _protocol, 673 net_buffer* buffer) 674 { 675 TRACE("%s(%p, buffer %p)\n", __FUNCTION__, _protocol, buffer); 676 677 interface_protocol* protocol = (interface_protocol*)_protocol; 678 Interface* interface = (Interface*)protocol->interface; 679 680 if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) 681 device_interface_monitor_receive(interface->DeviceInterface(), buffer); 682 683 return protocol->device_module->send_data(protocol->device, buffer); 684 } 685 686 687 static status_t 688 interface_protocol_up(net_datalink_protocol* protocol) 689 { 690 TRACE("%s(%p)\n", __FUNCTION__, protocol); 691 return B_OK; 692 } 693 694 695 static void 696 interface_protocol_down(net_datalink_protocol* _protocol) 697 { 698 TRACE("%s(%p)\n", __FUNCTION__, _protocol); 699 700 interface_protocol* protocol = (interface_protocol*)_protocol; 701 Interface* interface = (Interface*)protocol->interface; 702 net_device_interface* deviceInterface = interface->DeviceInterface(); 703 704 if (deviceInterface->up_count == 0) 705 return; 706 707 deviceInterface->up_count--; 708 709 interface->WentDown(); 710 711 if (deviceInterface->up_count > 0) 712 return; 713 714 down_device_interface(deviceInterface); 715 } 716 717 718 static status_t 719 interface_protocol_change_address(net_datalink_protocol* protocol, 720 net_interface_address* interfaceAddress, int32 option, 721 const struct sockaddr* oldAddress, const struct sockaddr* newAddress) 722 { 723 TRACE("%s(%p, interface address %p, option %s, old %p, new %p)\n", 724 __FUNCTION__, protocol, interfaceAddress, option_to_string(option), 725 oldAddress, newAddress); 726 727 switch (option) { 728 case SIOCSIFADDR: 729 case SIOCSIFNETMASK: 730 case SIOCSIFBRDADDR: 731 case SIOCSIFDSTADDR: 732 case SIOCDIFADDR: 733 return update_interface_address((InterfaceAddress*)interfaceAddress, 734 option, oldAddress, newAddress); 735 } 736 737 return B_OK; 738 } 739 740 741 static status_t 742 interface_protocol_control(net_datalink_protocol* _protocol, int32 option, 743 void* argument, size_t length) 744 { 745 TRACE("%s(%p, option %s, argument %p, length %zu)\n", __FUNCTION__, 746 _protocol, option_to_string(option), argument, length); 747 748 interface_protocol* protocol = (interface_protocol*)_protocol; 749 Interface* interface = (Interface*)protocol->interface; 750 751 switch (option) { 752 case SIOCGIFADDR: 753 case SIOCGIFNETMASK: 754 case SIOCGIFBRDADDR: 755 case SIOCGIFDSTADDR: 756 { 757 if (length < sizeof(ifreq)) 758 return B_BAD_VALUE; 759 760 ifreq request; 761 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) 762 return B_BAD_ADDRESS; 763 764 InterfaceAddress* interfaceAddress 765 = get_interface_address(&request.ifr_addr); 766 if (interfaceAddress == NULL) { 767 interfaceAddress 768 = interface->FirstForFamily(protocol->domain->family); 769 if (interfaceAddress == NULL) 770 return B_BAD_VALUE; 771 } 772 773 size_t maxLength = length - offsetof(ifreq, ifr_addr); 774 775 status_t status = fill_address( 776 *interfaceAddress->AddressFor(option), 777 &((struct ifreq*)argument)->ifr_addr, maxLength); 778 779 interfaceAddress->ReleaseReference(); 780 return status; 781 } 782 783 case B_SOCKET_COUNT_ALIASES: 784 { 785 ifreq request; 786 request.ifr_count = interface->CountAddresses(); 787 788 return user_memcpy(&((struct ifreq*)argument)->ifr_count, 789 &request.ifr_count, sizeof(request.ifr_count)); 790 } 791 792 case B_SOCKET_GET_ALIAS: 793 { 794 ifaliasreq request; 795 if (user_memcpy(&request, argument, sizeof(ifaliasreq)) != B_OK) 796 return B_BAD_ADDRESS; 797 798 InterfaceAddress* address = NULL; 799 if (request.ifra_index < 0) { 800 if (!protocol->domain->address_module->is_empty_address( 801 (const sockaddr*)&request.ifra_addr, false)) { 802 // Find first address that matches the local address 803 address = interface->AddressForLocal(protocol->domain, 804 (const sockaddr*)&request.ifra_addr); 805 } else { 806 // Find first address for family 807 address = interface->FirstForFamily( 808 protocol->domain->family); 809 } 810 811 request.ifra_index = interface->IndexOfAddress(address); 812 } else 813 address = interface->AddressAt(request.ifra_index); 814 if (address == NULL) 815 return B_BAD_VALUE; 816 817 // Copy index (in case none was specified) 818 status_t status = user_memcpy( 819 &((struct ifaliasreq*)argument)->ifra_index, 820 &request.ifra_index, sizeof(request.ifra_index)); 821 822 // Copy address info 823 if (status == B_OK) { 824 status = fill_address(address->local, 825 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_addr, 826 sizeof(sockaddr_storage)); 827 } 828 if (status == B_OK) { 829 status = fill_address(address->mask, 830 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_mask, 831 sizeof(sockaddr_storage)); 832 } 833 if (status == B_OK) { 834 status = fill_address(address->destination, 835 (sockaddr*)&((struct ifaliasreq*)argument) 836 ->ifra_destination, 837 sizeof(sockaddr_storage)); 838 } 839 840 address->ReleaseReference(); 841 842 return status; 843 } 844 845 case SIOCGIFFLAGS: 846 { 847 // get flags 848 struct ifreq request; 849 request.ifr_flags = interface->flags | interface->device->flags; 850 851 return user_memcpy(&((struct ifreq*)argument)->ifr_flags, 852 &request.ifr_flags, sizeof(request.ifr_flags)); 853 } 854 855 case SIOCGIFSTATS: 856 { 857 // get stats 858 return user_memcpy(&((struct ifreq*)argument)->ifr_stats, 859 &interface->DeviceInterface()->device->stats, 860 sizeof(struct ifreq_stats)); 861 } 862 863 case SIOCGIFTYPE: 864 { 865 // get type 866 struct ifreq request; 867 request.ifr_type = interface->type; 868 869 return user_memcpy(&((struct ifreq*)argument)->ifr_type, 870 &request.ifr_type, sizeof(request.ifr_type)); 871 } 872 873 case SIOCGIFMTU: 874 { 875 // get MTU 876 struct ifreq request; 877 request.ifr_mtu = interface->mtu; 878 879 return user_memcpy(&((struct ifreq*)argument)->ifr_mtu, 880 &request.ifr_mtu, sizeof(request.ifr_mtu)); 881 } 882 case SIOCSIFMTU: 883 { 884 // set MTU 885 struct ifreq request; 886 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 887 return B_BAD_ADDRESS; 888 889 // check for valid bounds 890 if (request.ifr_mtu < 100 891 || (uint32)request.ifr_mtu > interface->device->mtu) 892 return B_BAD_VALUE; 893 894 interface->mtu = request.ifr_mtu; 895 notify_interface_changed(interface); 896 return B_OK; 897 } 898 899 case SIOCSIFMEDIA: 900 { 901 // set media 902 struct ifreq request; 903 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK) 904 return B_BAD_ADDRESS; 905 906 status_t status 907 = interface->device->module->set_media( 908 interface->device, request.ifr_media); 909 if (status == B_NOT_SUPPORTED) { 910 // TODO: this isn't so nice, and should be solved differently 911 // (for example by removing the set_media() call altogether, or 912 // making it able to deal properly with FreeBSD drivers as well) 913 // try driver directly 914 status = interface->device->module->control( 915 interface->device, SIOCSIFMEDIA, &request, sizeof(request)); 916 } 917 918 return status; 919 } 920 case SIOCGIFMEDIA: 921 { 922 // get media 923 if (length < sizeof(ifmediareq)) 924 return B_BAD_VALUE; 925 926 struct ifmediareq request; 927 if (user_memcpy(&request, argument, sizeof(ifmediareq)) != B_OK) 928 return B_BAD_ADDRESS; 929 930 // TODO: see above. 931 if (interface->device->module->control(interface->device, 932 SIOCGIFMEDIA, &request, 933 sizeof(struct ifmediareq)) != B_OK) { 934 memset(&request, 0, sizeof(struct ifmediareq)); 935 request.ifm_active = request.ifm_current 936 = interface->device->media; 937 } 938 939 return user_memcpy(argument, &request, sizeof(struct ifmediareq)); 940 } 941 942 case SIOCGIFMETRIC: 943 { 944 // get metric 945 struct ifreq request; 946 request.ifr_metric = interface->metric; 947 948 return user_memcpy(&((struct ifreq*)argument)->ifr_metric, 949 &request.ifr_metric, sizeof(request.ifr_metric)); 950 } 951 case SIOCSIFMETRIC: 952 { 953 // set metric 954 struct ifreq request; 955 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 956 return B_BAD_ADDRESS; 957 958 interface->metric = request.ifr_metric; 959 notify_interface_changed(interface); 960 return B_OK; 961 } 962 963 case SIOCADDRT: 964 case SIOCDELRT: 965 // interface related route options 966 return control_routes(interface, protocol->domain, option, argument, 967 length); 968 } 969 970 return protocol->device_module->control(protocol->device, 971 option, argument, length); 972 } 973 974 975 static status_t 976 interface_protocol_join_multicast(net_datalink_protocol* _protocol, 977 const sockaddr* address) 978 { 979 interface_protocol* protocol = (interface_protocol*)_protocol; 980 981 return protocol->device_module->add_multicast(protocol->device, address); 982 } 983 984 985 static status_t 986 interface_protocol_leave_multicast(net_datalink_protocol* _protocol, 987 const sockaddr* address) 988 { 989 interface_protocol* protocol = (interface_protocol*)_protocol; 990 991 return protocol->device_module->remove_multicast(protocol->device, 992 address); 993 } 994 995 996 net_datalink_module_info gNetDatalinkModule = { 997 { 998 NET_DATALINK_MODULE_NAME, 999 0, 1000 datalink_std_ops 1001 }, 1002 1003 datalink_control, 1004 datalink_send_routed_data, 1005 datalink_send_data, 1006 1007 datalink_is_local_address, 1008 datalink_is_local_link_address, 1009 1010 datalink_get_interface, 1011 datalink_get_interface_with_address, 1012 datalink_put_interface, 1013 1014 datalink_get_interface_address, 1015 datalink_get_next_interface_address, 1016 datalink_put_interface_address, 1017 1018 datalink_join_multicast, 1019 datalink_leave_multicast, 1020 1021 add_route, 1022 remove_route, 1023 get_route, 1024 get_buffer_route, 1025 put_route, 1026 register_route_info, 1027 unregister_route_info, 1028 update_route_info 1029 }; 1030 1031 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = { 1032 { 1033 NULL, 1034 0, 1035 NULL 1036 }, 1037 interface_protocol_init, 1038 interface_protocol_uninit, 1039 interface_protocol_send_data, 1040 interface_protocol_up, 1041 interface_protocol_down, 1042 interface_protocol_change_address, 1043 interface_protocol_control, 1044 interface_protocol_join_multicast, 1045 interface_protocol_leave_multicast, 1046 }; 1047