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