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