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