1 /* 2 * Copyright 2006-2009, 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 "datalink.h" 12 #include "domains.h" 13 #include "interfaces.h" 14 #include "routes.h" 15 #include "stack_private.h" 16 #include "utility.h" 17 18 #include <net_device.h> 19 #include <KernelExport.h> 20 #include <util/AutoLock.h> 21 22 #include <net/if.h> 23 #include <net/if_dl.h> 24 #include <net/if_media.h> 25 #include <net/route.h> 26 #include <sys/sockio.h> 27 28 #include <new> 29 #include <stdlib.h> 30 #include <stdio.h> 31 #include <string.h> 32 33 34 struct datalink_protocol : net_protocol { 35 struct net_domain_private* domain; 36 }; 37 38 struct interface_protocol : net_datalink_protocol { 39 struct net_device_module_info* device_module; 40 struct net_device* device; 41 }; 42 43 44 /*! A service thread for each device interface. It just reads as many packets 45 as availabe, deframes them, and puts them into the receive queue of the 46 device interface. 47 */ 48 static status_t 49 device_reader_thread(void* _interface) 50 { 51 net_device_interface* interface = (net_device_interface*)_interface; 52 net_device* device = interface->device; 53 status_t status = B_OK; 54 55 RecursiveLocker locker(interface->receive_lock); 56 57 while ((device->flags & IFF_UP) != 0) { 58 locker.Unlock(); 59 60 net_buffer* buffer; 61 status = device->module->receive_data(device, &buffer); 62 63 locker.Lock(); 64 65 if (status == B_OK) { 66 // feed device monitors 67 DeviceMonitorList::Iterator iterator = 68 interface->monitor_funcs.GetIterator(); 69 while (net_device_monitor* monitor = iterator.Next()) { 70 monitor->receive(monitor, buffer); 71 } 72 73 buffer->interface = NULL; 74 buffer->type = interface->deframe_func(interface->device, buffer); 75 if (buffer->type < 0) { 76 gNetBufferModule.free(buffer); 77 continue; 78 } 79 80 fifo_enqueue_buffer(&interface->receive_queue, buffer); 81 } else { 82 // In case of error, give the other threads some 83 // time to run since this is a high priority time thread. 84 snooze(10000); 85 } 86 } 87 88 return status; 89 } 90 91 92 static struct sockaddr** 93 interface_address(net_interface* interface, int32 option) 94 { 95 switch (option) { 96 case SIOCSIFADDR: 97 case SIOCGIFADDR: 98 return &interface->address; 99 100 case SIOCSIFNETMASK: 101 case SIOCGIFNETMASK: 102 return &interface->mask; 103 104 case SIOCSIFBRDADDR: 105 case SIOCSIFDSTADDR: 106 case SIOCGIFBRDADDR: 107 case SIOCGIFDSTADDR: 108 return &interface->destination; 109 110 default: 111 return NULL; 112 } 113 } 114 115 116 /*! Removes the default routes as set by add_default_routes() again. */ 117 static void 118 remove_default_routes(net_interface_private* interface, int32 option) 119 { 120 net_route route; 121 route.destination = interface->address; 122 route.gateway = NULL; 123 route.interface = interface; 124 125 if (interface->mask != NULL 126 && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 127 route.mask = interface->mask; 128 route.flags = 0; 129 remove_route(interface->domain, &route); 130 } 131 132 if (option == SIOCSIFADDR) { 133 route.mask = NULL; 134 route.flags = RTF_LOCAL | RTF_HOST; 135 remove_route(interface->domain, &route); 136 } 137 } 138 139 140 /*! Adds the default routes that every interface needs, ie. the local host 141 route, and one for the subnet (if set). 142 */ 143 static void 144 add_default_routes(net_interface_private* interface, int32 option) 145 { 146 net_route route; 147 route.destination = interface->address; 148 route.gateway = NULL; 149 route.interface = interface; 150 151 if (interface->mask != NULL 152 && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) { 153 route.mask = interface->mask; 154 route.flags = 0; 155 add_route(interface->domain, &route); 156 } 157 158 if (option == SIOCSIFADDR) { 159 route.mask = NULL; 160 route.flags = RTF_LOCAL | RTF_HOST; 161 add_route(interface->domain, &route); 162 } 163 } 164 165 166 static sockaddr* 167 reallocate_address(sockaddr** _address, uint32 size) 168 { 169 sockaddr* address = *_address; 170 171 size = max_c(size, sizeof(struct sockaddr)); 172 if (address != NULL && address->sa_len >= size) 173 return address; 174 175 address = (sockaddr*)malloc(size); 176 if (address == NULL) 177 return NULL; 178 179 free(*_address); 180 *_address = address; 181 182 return address; 183 } 184 185 186 static status_t 187 datalink_control_interface(net_domain_private* domain, int32 option, 188 void* value, size_t* _length, size_t expected, bool getByName) 189 { 190 if (*_length < expected) 191 return B_BAD_VALUE; 192 193 ifreq request; 194 memset(&request, 0, sizeof(request)); 195 196 if (user_memcpy(&request, value, expected) < B_OK) 197 return B_BAD_ADDRESS; 198 199 RecursiveLocker _(domain->lock); 200 net_interface* interface = NULL; 201 202 if (getByName) 203 interface = find_interface(domain, request.ifr_name); 204 else 205 interface = find_interface(domain, request.ifr_index); 206 207 status_t status = interface == NULL ? ENODEV : B_OK; 208 209 switch (option) { 210 case SIOCGIFINDEX: 211 if (interface) 212 request.ifr_index = interface->index; 213 else 214 request.ifr_index = 0; 215 break; 216 217 case SIOCGIFNAME: 218 if (interface) 219 strlcpy(request.ifr_name, interface->name, IF_NAMESIZE); 220 else 221 status = B_BAD_VALUE; // TODO: should be ENXIO? 222 break; 223 } 224 225 if (status < B_OK) 226 return status; 227 228 return user_memcpy(value, &request, sizeof(ifreq)); 229 } 230 231 232 // #pragma mark - datalink module 233 234 235 status_t 236 datalink_control(net_domain* _domain, int32 option, void* value, 237 size_t* _length) 238 { 239 net_domain_private* domain = (net_domain_private*)_domain; 240 if (domain == NULL || domain->family == AF_LINK) { 241 // the AF_LINK family is already handled completely in the link protocol 242 return B_BAD_VALUE; 243 } 244 245 switch (option) { 246 case SIOCGIFINDEX: 247 return datalink_control_interface(domain, option, value, _length, 248 IF_NAMESIZE, true); 249 case SIOCGIFNAME: 250 return datalink_control_interface(domain, option, value, _length, 251 sizeof(ifreq), false); 252 253 case SIOCDIFADDR: 254 case SIOCSIFFLAGS: 255 { 256 struct ifreq request; 257 if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK) 258 return B_BAD_ADDRESS; 259 260 return domain_interface_control(domain, option, &request); 261 } 262 263 case SIOCAIFADDR: 264 { 265 // add new interface address 266 struct ifreq request; 267 if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK) 268 return B_BAD_ADDRESS; 269 270 return add_interface_to_domain(domain, request); 271 } 272 273 case SIOCGIFCOUNT: 274 { 275 // count number of interfaces 276 struct ifconf config; 277 config.ifc_value = count_domain_interfaces(); 278 279 return user_memcpy(value, &config, sizeof(struct ifconf)); 280 } 281 282 case SIOCGIFCONF: 283 { 284 // retrieve ifreqs for all interfaces 285 struct ifconf config; 286 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) 287 return B_BAD_ADDRESS; 288 289 status_t result = list_domain_interfaces(config.ifc_buf, 290 (size_t*)&config.ifc_len); 291 if (result != B_OK) 292 return result; 293 294 return user_memcpy(value, &config, sizeof(struct ifconf)); 295 } 296 297 case SIOCGRTSIZE: 298 { 299 // determine size of buffer to hold the routing table 300 struct ifconf config; 301 config.ifc_value = route_table_size(domain); 302 303 return user_memcpy(value, &config, sizeof(struct ifconf)); 304 } 305 case SIOCGRTTABLE: 306 { 307 // retrieve all routes for this domain 308 struct ifconf config; 309 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK) 310 return B_BAD_ADDRESS; 311 312 return list_routes(domain, config.ifc_buf, config.ifc_len); 313 } 314 case SIOCGETRT: 315 return get_route_information(domain, value, *_length); 316 317 default: 318 { 319 // try to pass the request to an existing interface 320 struct ifreq request; 321 if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK) 322 return B_BAD_ADDRESS; 323 324 RecursiveLocker _(domain->lock); 325 326 net_interface* interface = find_interface(domain, 327 request.ifr_name); 328 if (interface == NULL) 329 return B_BAD_VALUE; 330 331 // pass the request into the datalink protocol stack 332 return interface->first_info->control( 333 interface->first_protocol, option, value, *_length); 334 } 335 } 336 return B_BAD_VALUE; 337 } 338 339 340 status_t 341 datalink_send_data(struct net_route* route, net_buffer* buffer) 342 { 343 net_interface_private* interface = 344 (net_interface_private*)route->interface; 345 346 //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n", 347 // buffer->size, interface->name, route->flags); 348 349 if (route->flags & RTF_REJECT) 350 return ENETUNREACH; 351 352 if (route->flags & RTF_LOCAL) { 353 // we set the interface here so the buffer is delivered directly 354 // to the domain in interfaces.cpp:device_consumer_thread() 355 buffer->interface = interface; 356 // this one goes back to the domain directly 357 return fifo_enqueue_buffer( 358 &interface->device_interface->receive_queue, buffer); 359 } 360 361 if (route->flags & RTF_GATEWAY) { 362 // this route involves a gateway, we need to use the gateway address 363 // instead of the destination address: 364 if (route->gateway == NULL) 365 return B_MISMATCHED_VALUES; 366 memcpy(buffer->destination, route->gateway, route->gateway->sa_len); 367 } 368 369 // this goes out to the datalink protocols 370 return interface->first_info->send_data(interface->first_protocol, buffer); 371 } 372 373 374 status_t 375 datalink_send_datagram(net_protocol* protocol, net_domain* domain, 376 net_buffer* buffer) 377 { 378 if (protocol == NULL && domain == NULL) 379 return B_BAD_VALUE; 380 381 net_protocol_module_info* module = protocol ? protocol->module 382 : domain->module; 383 384 if (domain == NULL) 385 domain = protocol->module->get_domain(protocol); 386 387 net_route* route = NULL; 388 status_t status; 389 if (protocol != NULL && protocol->socket->bound_to_device > 0) { 390 status = get_device_route(domain, protocol->socket->bound_to_device, 391 &route); 392 } else 393 status = get_buffer_route(domain, buffer, &route); 394 if (status < B_OK) 395 return status; 396 397 status = module->send_routed_data(protocol, route, buffer); 398 put_route(domain, route); 399 return status; 400 } 401 402 403 /*! Tests if \a address is a local address in the domain. 404 405 \param _interface will be set to the interface belonging to that address 406 if non-NULL. 407 \param _matchedType will be set to either zero or MSG_BCAST if non-NULL. 408 */ 409 bool 410 datalink_is_local_address(net_domain* _domain, const struct sockaddr* address, 411 net_interface** _interface, uint32* _matchedType) 412 { 413 net_domain_private* domain = (net_domain_private*)_domain; 414 if (domain == NULL || address == NULL) 415 return false; 416 417 RecursiveLocker locker(domain->lock); 418 419 net_interface* interface = NULL; 420 uint32 matchedType = 0; 421 422 while (true) { 423 interface = (net_interface*)list_get_next_item( 424 &domain->interfaces, interface); 425 if (interface == NULL) 426 break; 427 if (interface->address == NULL) 428 continue; 429 430 // check for matching unicast address first 431 if (domain->address_module->equal_addresses(interface->address, address)) 432 break; 433 434 // check for matching broadcast address if interface supports 435 // broadcasting (IFF_BROADCAST is a link-level flag, so it is 436 // a property of the device) 437 if ((interface->device->flags & IFF_BROADCAST) != 0 438 && domain->address_module->equal_addresses(interface->destination, 439 address)) { 440 matchedType = MSG_BCAST; 441 break; 442 } 443 } 444 445 if (interface == NULL) 446 return false; 447 448 if (_interface != NULL) 449 *_interface = interface; 450 if (_matchedType != NULL) 451 *_matchedType = matchedType; 452 return true; 453 } 454 455 456 /*! Tests if \a address is a local link address in the domain. 457 458 \param unconfigured only unconfigured interfaces are taken into account. 459 \param _interface will be set to the interface belonging to that address 460 if non-NULL. 461 */ 462 bool 463 datalink_is_local_link_address(net_domain* _domain, bool unconfigured, 464 const struct sockaddr* address, net_interface** _interface) 465 { 466 net_domain_private* domain = (net_domain_private*)_domain; 467 if (domain == NULL || address == NULL || address->sa_family != AF_LINK) 468 return false; 469 470 RecursiveLocker locker(domain->lock); 471 472 sockaddr_dl& linkAddress = *(sockaddr_dl*)address; 473 net_interface* interface = NULL; 474 475 while (true) { 476 interface = (net_interface*)list_get_next_item( 477 &domain->interfaces, interface); 478 if (interface == NULL) 479 break; 480 481 if (unconfigured && interface->address != NULL 482 && (interface->flags & IFF_CONFIGURING) == 0) 483 continue; 484 485 if (linkAddress.sdl_alen == interface->device->address.length 486 && memcmp(LLADDR(&linkAddress), interface->device->address.data, 487 linkAddress.sdl_alen) == 0) { 488 // link address matches 489 if (_interface != NULL) 490 *_interface = interface; 491 return true; 492 } 493 } 494 495 return false; 496 } 497 498 499 net_interface* 500 datalink_get_interface_with_address(net_domain* _domain, 501 const sockaddr* address) 502 { 503 net_domain_private* domain = (net_domain_private*)_domain; 504 if (domain == NULL) 505 return NULL; 506 507 RecursiveLocker _(domain->lock); 508 509 net_interface* interface = NULL; 510 511 while (true) { 512 interface = (net_interface*)list_get_next_item( 513 &domain->interfaces, interface); 514 if (interface == NULL) 515 break; 516 517 if (address == NULL) 518 return interface; 519 520 if (domain->address_module->equal_addresses(interface->address, 521 address)) 522 return interface; 523 } 524 525 return NULL; 526 } 527 528 529 net_interface* 530 datalink_get_interface(net_domain* domain, uint32 index) 531 { 532 if (index == 0) 533 return datalink_get_interface_with_address(domain, NULL); 534 535 return find_interface(domain, index); 536 } 537 538 539 static status_t 540 datalink_std_ops(int32 op, ...) 541 { 542 switch (op) { 543 case B_MODULE_INIT: 544 case B_MODULE_UNINIT: 545 return B_OK; 546 547 default: 548 return B_ERROR; 549 } 550 } 551 552 553 // #pragma mark - net_datalink_protocol 554 555 556 status_t 557 interface_protocol_init(struct net_interface* _interface, 558 net_datalink_protocol** _protocol) 559 { 560 net_interface_private* interface = (net_interface_private*)_interface; 561 562 interface_protocol* protocol = new (std::nothrow) interface_protocol; 563 if (protocol == NULL) 564 return B_NO_MEMORY; 565 566 protocol->device_module = interface->device->module; 567 protocol->device = interface->device; 568 569 *_protocol = protocol; 570 return B_OK; 571 } 572 573 574 status_t 575 interface_protocol_uninit(net_datalink_protocol* protocol) 576 { 577 delete protocol; 578 return B_OK; 579 } 580 581 582 status_t 583 interface_protocol_send_data(net_datalink_protocol* _protocol, 584 net_buffer* buffer) 585 { 586 interface_protocol* protocol = (interface_protocol*)_protocol; 587 net_interface_private* interface 588 = (net_interface_private*)protocol->interface; 589 590 // TODO: Need to think about this locking. We can't obtain the 591 // RX Lock here (nor would it make sense) as the ARP 592 // module calls send_data() with it's lock held (similiar 593 // to the domain lock, which would violate the locking 594 // protocol). 595 596 DeviceMonitorList::Iterator iterator = 597 interface->device_interface->monitor_funcs.GetIterator(); 598 while (iterator.HasNext()) { 599 net_device_monitor* monitor = iterator.Next(); 600 monitor->receive(monitor, buffer); 601 } 602 603 return protocol->device_module->send_data(protocol->device, buffer); 604 } 605 606 607 status_t 608 interface_protocol_up(net_datalink_protocol* _protocol) 609 { 610 interface_protocol* protocol = (interface_protocol*)_protocol; 611 net_device_interface* deviceInterface = 612 ((net_interface_private*)protocol->interface)->device_interface; 613 net_device* device = protocol->device; 614 615 // This function is called with the RX lock held. 616 617 if (deviceInterface->up_count != 0) { 618 deviceInterface->up_count++; 619 return B_OK; 620 } 621 622 status_t status = protocol->device_module->up(device); 623 if (status < B_OK) 624 return status; 625 626 if (device->module->receive_data != NULL) { 627 // give the thread a nice name 628 char name[B_OS_NAME_LENGTH]; 629 snprintf(name, sizeof(name), "%s reader", device->name); 630 631 deviceInterface->reader_thread = 632 spawn_kernel_thread(device_reader_thread, name, 633 B_REAL_TIME_DISPLAY_PRIORITY - 10, deviceInterface); 634 if (deviceInterface->reader_thread < B_OK) 635 return deviceInterface->reader_thread; 636 } 637 638 device->flags |= IFF_UP; 639 640 if (device->module->receive_data != NULL) 641 resume_thread(deviceInterface->reader_thread); 642 643 deviceInterface->up_count = 1; 644 return B_OK; 645 } 646 647 648 void 649 interface_protocol_down(net_datalink_protocol* _protocol) 650 { 651 interface_protocol* protocol = (interface_protocol*)_protocol; 652 net_device_interface* deviceInterface = 653 ((net_interface_private*)protocol->interface)->device_interface; 654 655 // This function is called with the RX lock held. 656 if (deviceInterface->up_count == 0) 657 return; 658 659 deviceInterface->up_count--; 660 661 domain_interface_went_down(protocol->interface); 662 663 if (deviceInterface->up_count > 0) 664 return; 665 666 down_device_interface(deviceInterface); 667 } 668 669 670 status_t 671 interface_protocol_control(net_datalink_protocol* _protocol, int32 option, 672 void* argument, size_t length) 673 { 674 interface_protocol* protocol = (interface_protocol*)_protocol; 675 net_interface_private* interface 676 = (net_interface_private*)protocol->interface; 677 678 switch (option) { 679 case SIOCSIFADDR: 680 case SIOCSIFNETMASK: 681 case SIOCSIFBRDADDR: 682 case SIOCSIFDSTADDR: 683 { 684 // set logical interface address 685 struct ifreq request; 686 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 687 return B_BAD_ADDRESS; 688 689 sockaddr** _address = interface_address(interface, option); 690 if (_address == NULL) 691 return B_BAD_VALUE; 692 693 // allocate new address if needed 694 sockaddr* address = reallocate_address(_address, 695 request.ifr_addr.sa_len); 696 697 // copy new address over 698 if (address != NULL) { 699 remove_default_routes(interface, option); 700 memcpy(address, &request.ifr_addr, request.ifr_addr.sa_len); 701 702 if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { 703 // reset netmask and broadcast addresses to defaults 704 sockaddr* netmask = NULL; 705 sockaddr* oldNetmask = NULL; 706 if (option == SIOCSIFADDR) { 707 netmask = reallocate_address(&interface->mask, 708 request.ifr_addr.sa_len); 709 } else 710 oldNetmask = address; 711 712 sockaddr* broadcast = reallocate_address( 713 &interface->destination, request.ifr_addr.sa_len); 714 715 interface->domain->address_module->set_to_defaults( 716 netmask, broadcast, interface->address, oldNetmask); 717 } 718 719 add_default_routes(interface, option); 720 } 721 722 return address != NULL ? B_OK : B_NO_MEMORY; 723 } 724 725 case SIOCGIFADDR: 726 case SIOCGIFNETMASK: 727 case SIOCGIFBRDADDR: 728 case SIOCGIFDSTADDR: 729 { 730 // get logical interface address 731 sockaddr** _address = interface_address(interface, option); 732 if (_address == NULL) 733 return B_BAD_VALUE; 734 735 struct ifreq request; 736 737 sockaddr* address = *_address; 738 if (address != NULL) 739 memcpy(&request.ifr_addr, address, address->sa_len); 740 else { 741 request.ifr_addr.sa_len = 2; 742 request.ifr_addr.sa_family = AF_UNSPEC; 743 } 744 745 // copy address over 746 return user_memcpy(&((struct ifreq*)argument)->ifr_addr, 747 &request.ifr_addr, request.ifr_addr.sa_len); 748 } 749 750 case SIOCGIFFLAGS: 751 { 752 // get flags 753 struct ifreq request; 754 request.ifr_flags = interface->flags | interface->device->flags; 755 756 return user_memcpy(&((struct ifreq*)argument)->ifr_flags, 757 &request.ifr_flags, sizeof(request.ifr_flags)); 758 } 759 760 case SIOCGIFPARAM: 761 { 762 // get interface parameter 763 struct ifreq request; 764 strlcpy(request.ifr_parameter.base_name, interface->base_name, IF_NAMESIZE); 765 strlcpy(request.ifr_parameter.device, 766 interface->device_interface->device->name, IF_NAMESIZE); 767 request.ifr_parameter.sub_type = 0; 768 // TODO: for now, we ignore the sub type... 769 770 return user_memcpy(&((struct ifreq*)argument)->ifr_parameter, 771 &request.ifr_parameter, sizeof(request.ifr_parameter)); 772 } 773 774 case SIOCGIFSTATS: 775 { 776 // get stats 777 return user_memcpy(&((struct ifreq*)argument)->ifr_stats, 778 &interface->device_interface->device->stats, 779 sizeof(struct ifreq_stats)); 780 } 781 782 case SIOCGIFTYPE: 783 { 784 // get type 785 struct ifreq request; 786 request.ifr_type = interface->type; 787 788 return user_memcpy(&((struct ifreq*)argument)->ifr_type, 789 &request.ifr_type, sizeof(request.ifr_type)); 790 } 791 792 case SIOCGIFMTU: 793 { 794 // get MTU 795 struct ifreq request; 796 request.ifr_mtu = interface->mtu; 797 798 return user_memcpy(&((struct ifreq*)argument)->ifr_mtu, 799 &request.ifr_mtu, sizeof(request.ifr_mtu)); 800 } 801 case SIOCSIFMTU: 802 { 803 // set MTU 804 struct ifreq request; 805 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 806 return B_BAD_ADDRESS; 807 808 // check for valid bounds 809 if (request.ifr_mtu < 100 810 || (uint32)request.ifr_mtu > interface->device->mtu) 811 return B_BAD_VALUE; 812 813 interface->mtu = request.ifr_mtu; 814 return B_OK; 815 } 816 817 case SIOCSIFMEDIA: 818 { 819 // set media 820 struct ifreq request; 821 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 822 return B_BAD_ADDRESS; 823 824 return interface->device_interface->device->module->set_media( 825 interface->device, request.ifr_media); 826 } 827 case SIOCGIFMEDIA: 828 { 829 // get media 830 struct ifreq request; 831 request.ifr_media = interface->device->media; 832 833 return user_memcpy(&((struct ifreq*)argument)->ifr_media, 834 &request.ifr_media, sizeof(request.ifr_media)); 835 } 836 837 case SIOCGIFMETRIC: 838 { 839 // get metric 840 struct ifreq request; 841 request.ifr_metric = interface->metric; 842 843 return user_memcpy(&((struct ifreq*)argument)->ifr_metric, 844 &request.ifr_metric, sizeof(request.ifr_metric)); 845 } 846 case SIOCSIFMETRIC: 847 { 848 // set metric 849 struct ifreq request; 850 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) 851 return B_BAD_ADDRESS; 852 853 interface->metric = request.ifr_metric; 854 return B_OK; 855 } 856 857 case SIOCADDRT: 858 case SIOCDELRT: 859 // interface related route options 860 return control_routes(interface, option, argument, length); 861 } 862 863 return protocol->device_module->control(protocol->device, 864 option, argument, length); 865 } 866 867 868 static status_t 869 interface_protocol_join_multicast(net_datalink_protocol* _protocol, 870 const sockaddr* address) 871 { 872 interface_protocol* protocol = (interface_protocol*)_protocol; 873 874 return protocol->device_module->add_multicast(protocol->device, address); 875 } 876 877 878 static status_t 879 interface_protocol_leave_multicast(net_datalink_protocol* _protocol, 880 const sockaddr* address) 881 { 882 interface_protocol* protocol = (interface_protocol*)_protocol; 883 884 return protocol->device_module->remove_multicast(protocol->device, 885 address); 886 } 887 888 889 net_datalink_module_info gNetDatalinkModule = { 890 { 891 NET_DATALINK_MODULE_NAME, 892 0, 893 datalink_std_ops 894 }, 895 896 datalink_control, 897 datalink_send_data, 898 datalink_send_datagram, 899 datalink_is_local_address, 900 datalink_is_local_link_address, 901 datalink_get_interface, 902 datalink_get_interface_with_address, 903 904 add_route, 905 remove_route, 906 get_route, 907 get_buffer_route, 908 put_route, 909 register_route_info, 910 unregister_route_info, 911 update_route_info 912 }; 913 914 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = { 915 { 916 NULL, 917 0, 918 NULL 919 }, 920 interface_protocol_init, 921 interface_protocol_uninit, 922 interface_protocol_send_data, 923 interface_protocol_up, 924 interface_protocol_down, 925 interface_protocol_control, 926 interface_protocol_join_multicast, 927 interface_protocol_leave_multicast, 928 }; 929