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