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