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