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 */ 8 9 10 #include "ancillary_data.h" 11 #include "domains.h" 12 #include "interfaces.h" 13 #include "link.h" 14 #include "stack_private.h" 15 #include "utility.h" 16 17 #include <net_datalink_protocol.h> 18 #include <net_device.h> 19 #include <net_protocol.h> 20 #include <net_stack.h> 21 22 #include <lock.h> 23 #include <util/AutoLock.h> 24 #include <util/khash.h> 25 26 #include <KernelExport.h> 27 28 #include <net/if_types.h> 29 #include <new> 30 #include <stdarg.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 35 //#define TRACE_STACK 36 #ifdef TRACE_STACK 37 # define TRACE(x) dprintf x 38 #else 39 # define TRACE(x) ; 40 #endif 41 42 #define MAX_CHAIN_MODULES 5 43 44 struct chain; 45 typedef DoublyLinkedList<chain> ChainList; 46 47 struct chain_key { 48 int family; 49 int type; 50 int protocol; 51 }; 52 53 struct family { 54 family(int type); 55 56 void Acquire(); 57 void Release(); 58 59 static int Compare(void* _family, const void* _key); 60 static uint32 Hash(void* _family, const void* _key, uint32 range); 61 static struct family* Lookup(int type); 62 static struct family* Add(int type); 63 64 struct family* next; 65 int type; 66 int32 ref_count; 67 ChainList chains; 68 }; 69 70 struct chain : DoublyLinkedListLinkImpl<chain> { 71 chain(int family, int type, int protocol); 72 ~chain(); 73 74 status_t Acquire(); 75 void Release(); 76 void Uninitialize(); 77 78 static int Compare(void* _chain, const void* _key); 79 static uint32 Hash(void* _chain, const void* _key, uint32 range); 80 static struct chain* Lookup(hash_table* chains, int family, int type, 81 int protocol); 82 static struct chain* Add(hash_table* chains, int family, int type, 83 int protocol, va_list modules); 84 static struct chain* Add(hash_table* chains, int family, int type, 85 int protocol, ...); 86 static void DeleteChains(hash_table* chains); 87 88 chain* next; 89 struct family* parent; 90 91 int family; 92 int type; 93 int protocol; 94 95 int32 ref_count; 96 uint32 flags; 97 const char* modules[MAX_CHAIN_MODULES + 1]; 98 module_info* infos[MAX_CHAIN_MODULES + 1]; 99 }; 100 101 #define CHAIN_MISSING_MODULE 0x02 102 #define CHAIN_INITIALIZED 0x01 103 104 static mutex sChainLock; 105 static mutex sInitializeChainLock; 106 static hash_table* sProtocolChains; 107 static hash_table* sDatalinkProtocolChains; 108 static hash_table* sReceivingProtocolChains; 109 static hash_table* sFamilies; 110 static bool sInitialized; 111 112 113 family::family(int _type) 114 : 115 type(_type), 116 ref_count(0) 117 { 118 } 119 120 121 void 122 family::Acquire() 123 { 124 atomic_add(&ref_count, 1); 125 } 126 127 128 void 129 family::Release() 130 { 131 if (atomic_add(&ref_count, -1) > 1) 132 return; 133 134 TRACE(("family %d unused, uninit chains\n", type)); 135 MutexLocker _(sChainLock); 136 137 ChainList::Iterator iterator = chains.GetIterator(); 138 while (struct chain* chain = iterator.Next()) { 139 chain->Uninitialize(); 140 } 141 } 142 143 144 /*static*/ int 145 family::Compare(void* _family, const void* _key) 146 { 147 struct family* family = (struct family*)_family; 148 int key = (int)_key; 149 150 if (family->type == key) 151 return 0; 152 153 return 1; 154 } 155 156 157 /*static*/ uint32 158 family::Hash(void* _family, const void* _key, uint32 range) 159 { 160 struct family* family = (struct family*)_family; 161 int key = (int)_key; 162 163 if (family != NULL) 164 return family->type % range; 165 166 return key % range; 167 } 168 169 170 /*static*/ struct family* 171 family::Lookup(int type) 172 { 173 return (struct family*)hash_lookup(sFamilies, (void*)type); 174 } 175 176 177 /*static*/ struct family* 178 family::Add(int type) 179 { 180 struct family* family = new (std::nothrow) ::family(type); 181 if (family == NULL) 182 return NULL; 183 184 if (hash_insert(sFamilies, family) != B_OK) { 185 delete family; 186 return NULL; 187 } 188 189 return family; 190 } 191 192 193 // #pragma mark - 194 195 196 chain::chain(int _family, int _type, int _protocol) 197 : 198 family(_family), 199 type(_type), 200 protocol(_protocol), 201 ref_count(0), 202 flags(0) 203 { 204 parent = ::family::Lookup(family); 205 if (parent == NULL) 206 parent = ::family::Add(family); 207 208 //parent->chains.Add(this); 209 210 for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) { 211 modules[i] = NULL; 212 infos[i] = NULL; 213 } 214 } 215 216 217 chain::~chain() 218 { 219 for (int32 i = 0; i < MAX_CHAIN_MODULES; i++) { 220 free((char*)modules[i]); 221 } 222 223 //parent->chains.Remove(this); 224 } 225 226 227 status_t 228 chain::Acquire() 229 { 230 if (atomic_add(&ref_count, 1) > 0) { 231 if ((flags & CHAIN_MISSING_MODULE) != 0) { 232 atomic_add(&ref_count, -1); 233 return EAFNOSUPPORT; 234 } 235 236 while ((flags & CHAIN_INITIALIZED) == 0) { 237 mutex_lock(&sInitializeChainLock); 238 mutex_unlock(&sInitializeChainLock); 239 } 240 return B_OK; 241 } 242 243 parent->Acquire(); 244 245 if ((flags & CHAIN_INITIALIZED) != 0) 246 return B_OK; 247 248 TRACE(("initializing chain %d.%d.%d\n", family, type, protocol)); 249 MutexLocker locker(&sInitializeChainLock); 250 251 for (int32 i = 0; modules[i] != NULL; i++) { 252 if (get_module(modules[i], &infos[i]) < B_OK) { 253 flags |= CHAIN_MISSING_MODULE; 254 255 // put already opened modules 256 while (i-- > 0) { 257 put_module(modules[i]); 258 } 259 return EAFNOSUPPORT; 260 } 261 } 262 263 flags |= CHAIN_INITIALIZED; 264 return B_OK; 265 } 266 267 268 void 269 chain::Release() 270 { 271 if (atomic_add(&ref_count, -1) > 1) 272 return; 273 274 TRACE(("chain %d.%d.%d unused\n", family, type, protocol)); 275 parent->Release(); 276 } 277 278 279 void 280 chain::Uninitialize() 281 { 282 if ((flags & CHAIN_INITIALIZED) == 0) 283 return; 284 285 TRACE(("uninit chain %d.%d.%d\n", family, type, protocol)); 286 MutexLocker _(sInitializeChainLock); 287 288 for (int32 i = 0; modules[i] != NULL; i++) { 289 put_module(modules[i]); 290 } 291 292 flags &= ~CHAIN_INITIALIZED; 293 } 294 295 296 /*static*/ int 297 chain::Compare(void* _chain, const void* _key) 298 { 299 const chain_key* key = (const chain_key*)_key; 300 struct chain* chain = (struct chain*)_chain; 301 302 if (chain->family == key->family 303 && chain->type == key->type 304 && chain->protocol == key->protocol) 305 return 0; 306 307 return 1; 308 } 309 310 311 /*static*/ uint32 312 chain::Hash(void* _chain, const void* _key, uint32 range) 313 { 314 const chain_key* key = (const chain_key*)_key; 315 struct chain* chain = (struct chain*)_chain; 316 317 // TODO: check if this makes a good hash... 318 #define HASH(o) ((uint32)(((o)->family) ^ ((o)->type) ^ ((o)->protocol)) % range) 319 #if 0 320 TRACE(("%d.%d.%d: Hash: %lu\n", chain ? chain->family : key->family, 321 chain ? chain->type : key->type, chain ? chain->protocol : key->protocol, 322 chain ? HASH(chain) : HASH(key))); 323 #endif 324 325 if (chain != NULL) 326 return HASH(chain); 327 328 return HASH(key); 329 #undef HASH 330 } 331 332 333 /*static*/ struct chain* 334 chain::Lookup(hash_table* chains, int family, int type, int protocol) 335 { 336 struct chain_key key = { family, type, protocol }; 337 return (struct chain*)hash_lookup(chains, &key); 338 } 339 340 341 /*static*/ struct chain* 342 chain::Add(hash_table* chains, int family, int type, int protocol, 343 va_list modules) 344 { 345 struct chain* chain = new (std::nothrow) ::chain(family, type, protocol); 346 if (chain == NULL) 347 return NULL; 348 349 if (chain->parent == NULL || hash_insert(chains, chain) != B_OK) { 350 delete chain; 351 return NULL; 352 } 353 354 TRACE(("Add chain %d.%d.%d:\n", family, type, protocol)); 355 const char* module; 356 int32 count = 0; 357 358 while (true) { 359 module = va_arg(modules, const char*); 360 if (module == NULL) 361 break; 362 363 TRACE((" [%ld] %s\n", count, module)); 364 chain->modules[count] = strdup(module); 365 if (chain->modules[count] == NULL 366 || ++count >= MAX_CHAIN_MODULES) { 367 hash_remove(chains, chain); 368 delete chain; 369 return NULL; 370 } 371 } 372 373 if (chains == sProtocolChains && count == 0) { 374 hash_remove(chains, chain); 375 delete chain; 376 return NULL; 377 } 378 379 return chain; 380 } 381 382 383 /*static*/ struct chain* 384 chain::Add(hash_table* chains, int family, int type, int protocol, ...) 385 { 386 va_list modules; 387 va_start(modules, protocol); 388 389 struct chain* chain = Add(chains, family, type, 0, modules); 390 391 va_end(modules); 392 return chain; 393 } 394 395 396 /*static*/ void 397 chain::DeleteChains(hash_table* chains) 398 { 399 uint32 cookie = 0; 400 while (true) { 401 struct chain* chain = (struct chain*)hash_remove_first(chains, &cookie); 402 if (chain == NULL) 403 break; 404 405 chain->Uninitialize(); 406 delete chain; 407 } 408 } 409 410 411 // #pragma mark - 412 413 414 static void 415 uninit_domain_protocols(net_socket* socket) 416 { 417 net_protocol* protocol = socket->first_protocol; 418 while (protocol != NULL) { 419 net_protocol* next = protocol->next; 420 protocol->module->uninit_protocol(protocol); 421 422 protocol = next; 423 } 424 425 socket->first_protocol = NULL; 426 socket->first_info = NULL; 427 } 428 429 430 status_t 431 get_domain_protocols(net_socket* socket) 432 { 433 struct chain* chain; 434 435 { 436 MutexLocker _(sChainLock); 437 438 chain = chain::Lookup(sProtocolChains, socket->family, socket->type, 439 socket->type == SOCK_RAW ? 0 : socket->protocol); 440 // in SOCK_RAW mode, we ignore the protocol information 441 if (chain == NULL) { 442 // TODO: if we want to be POSIX compatible, we should also support 443 // the error codes EPROTONOSUPPORT and EPROTOTYPE. 444 return EAFNOSUPPORT; 445 } 446 } 447 448 // create net_protocol objects for the protocols in the chain 449 450 status_t status = chain->Acquire(); 451 if (status != B_OK) 452 return status; 453 454 net_protocol* last = NULL; 455 456 for (int32 i = 0; chain->infos[i] != NULL; i++) { 457 net_protocol* protocol = 458 ((net_protocol_module_info*)chain->infos[i])->init_protocol(socket); 459 if (protocol == NULL) { 460 // free protocols we already initialized 461 uninit_domain_protocols(socket); 462 chain->Release(); 463 return B_NO_MEMORY; 464 } 465 466 protocol->module = (net_protocol_module_info*)chain->infos[i]; 467 protocol->socket = socket; 468 protocol->next = NULL; 469 470 if (last == NULL) { 471 socket->first_protocol = protocol; 472 socket->first_info = protocol->module; 473 } else 474 last->next = protocol; 475 476 last = protocol; 477 } 478 479 return B_OK; 480 } 481 482 483 status_t 484 put_domain_protocols(net_socket* socket) 485 { 486 struct chain* chain; 487 488 { 489 MutexLocker _(sChainLock); 490 491 chain = chain::Lookup(sProtocolChains, socket->family, socket->type, 492 socket->protocol); 493 if (chain == NULL) 494 return B_ERROR; 495 } 496 497 uninit_domain_protocols(socket); 498 chain->Release(); 499 return B_OK; 500 } 501 502 503 static void 504 uninit_domain_datalink_protocols(net_interface* interface) 505 { 506 net_datalink_protocol* protocol = interface->first_protocol; 507 while (protocol != NULL) { 508 net_datalink_protocol* next = protocol->next; 509 protocol->module->uninit_protocol(protocol); 510 511 protocol = next; 512 } 513 514 interface->first_protocol = NULL; 515 interface->first_info = NULL; 516 } 517 518 519 status_t 520 get_domain_datalink_protocols(net_interface* _interface) 521 { 522 struct net_interface_private* interface = (net_interface_private*)_interface; 523 struct chain* chain; 524 525 { 526 MutexLocker _(sChainLock); 527 528 chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family, 529 interface->device_interface->device->type, 0); 530 if (chain == NULL) 531 return EAFNOSUPPORT; 532 } 533 534 // create net_protocol objects for the protocols in the chain 535 536 status_t status = chain->Acquire(); 537 if (status < B_OK) 538 return status; 539 540 net_datalink_protocol* last = NULL; 541 542 for (int32 i = 0; chain->infos[i] != NULL; i++) { 543 net_datalink_protocol* protocol; 544 status_t status = ((net_datalink_protocol_module_info*) 545 chain->infos[i])->init_protocol(interface, &protocol); 546 if (status < B_OK) { 547 // free protocols we already initialized 548 uninit_domain_datalink_protocols(interface); 549 chain->Release(); 550 return status; 551 } 552 553 protocol->module = (net_datalink_protocol_module_info*)chain->infos[i]; 554 protocol->interface = interface; 555 protocol->next = NULL; 556 557 if (last == NULL) { 558 interface->first_protocol = protocol; 559 interface->first_info = protocol->module; 560 } else 561 last->next = protocol; 562 563 last = protocol; 564 } 565 566 return B_OK; 567 } 568 569 570 status_t 571 put_domain_datalink_protocols(net_interface* _interface) 572 { 573 struct net_interface_private* interface = (net_interface_private*)_interface; 574 struct chain* chain; 575 576 { 577 MutexLocker _(sChainLock); 578 579 chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family, 580 interface->device_interface->device->type, 0); 581 if (chain == NULL) 582 return B_ERROR; 583 } 584 585 uninit_domain_datalink_protocols(interface); 586 chain->Release(); 587 return B_OK; 588 } 589 590 591 status_t 592 get_domain_receiving_protocol(net_domain* _domain, uint32 type, 593 net_protocol_module_info** _module) 594 { 595 struct net_domain_private* domain = (net_domain_private*)_domain; 596 struct chain* chain; 597 598 TRACE(("get_domain_receiving_protocol(family %d, type %lu)\n", 599 domain->family, type)); 600 601 { 602 MutexLocker _(sChainLock); 603 604 chain = chain::Lookup(sReceivingProtocolChains, domain->family, 605 type, 0); 606 if (chain == NULL) 607 return EAFNOSUPPORT; 608 } 609 610 status_t status = chain->Acquire(); 611 if (status != B_OK) 612 return status; 613 614 *_module = (net_protocol_module_info*)chain->infos[0]; 615 return B_OK; 616 } 617 618 619 status_t 620 put_domain_receiving_protocol(net_domain* _domain, uint32 type) 621 { 622 struct net_domain_private* domain = (net_domain_private*)_domain; 623 struct chain* chain; 624 625 { 626 MutexLocker _(sChainLock); 627 628 chain = chain::Lookup(sReceivingProtocolChains, domain->family, 629 type, 0); 630 if (chain == NULL) 631 return B_ERROR; 632 } 633 634 chain->Release(); 635 return B_OK; 636 } 637 638 639 status_t 640 register_domain_protocols(int family, int type, int protocol, ...) 641 { 642 if (type == SOCK_RAW) { 643 // in SOCK_RAW mode, we ignore the protocol information 644 protocol = 0; 645 } 646 647 MutexLocker locker(&sChainLock); 648 649 struct chain* chain = chain::Lookup(sProtocolChains, family, type, protocol); 650 if (chain != NULL) 651 return B_OK; 652 653 va_list modules; 654 va_start(modules, protocol); 655 656 chain = chain::Add(sProtocolChains, family, type, protocol, modules); 657 658 va_end(modules); 659 660 if (chain == NULL) 661 return B_NO_MEMORY; 662 663 return B_OK; 664 } 665 666 667 status_t 668 register_domain_datalink_protocols(int family, int type, ...) 669 { 670 TRACE(("register_domain_datalink_protocol(%d.%d)\n", family, type)); 671 MutexLocker locker(&sChainLock); 672 673 struct chain* chain 674 = chain::Lookup(sDatalinkProtocolChains, family, type, 0); 675 if (chain != NULL) 676 return B_OK; 677 678 va_list modules; 679 va_start(modules, type); 680 681 chain = chain::Add(sDatalinkProtocolChains, family, type, 0, modules); 682 683 va_end(modules); 684 685 if (chain == NULL) 686 return B_NO_MEMORY; 687 688 // Add datalink interface protocol as the last protocol in the chain; it's 689 // name stays unset, so that it won't be part of the release/acquire process. 690 691 uint32 count = 0; 692 while (chain->modules[count] != NULL) { 693 count++; 694 } 695 696 chain->infos[count] = (module_info*)&gDatalinkInterfaceProtocolModule; 697 return B_OK; 698 } 699 700 701 static status_t 702 register_domain_receiving_protocol(int family, int type, const char* moduleName) 703 { 704 TRACE(("register_domain_receiving_protocol(%d.%d, %s)\n", family, type, 705 moduleName)); 706 707 MutexLocker _(sChainLock); 708 709 struct chain* chain 710 = chain::Lookup(sReceivingProtocolChains, family, type, 0); 711 if (chain != NULL) 712 return B_OK; 713 714 chain = chain::Add(sReceivingProtocolChains, family, type, 0, moduleName, 715 NULL); 716 if (chain == NULL) 717 return B_NO_MEMORY; 718 719 return B_OK; 720 } 721 722 723 static void 724 scan_modules(const char* path) 725 { 726 void* cookie = open_module_list(path); 727 if (cookie == NULL) 728 return; 729 730 while (true) { 731 char name[B_FILE_NAME_LENGTH]; 732 size_t length = sizeof(name); 733 if (read_next_module_name(cookie, name, &length) != B_OK) 734 break; 735 736 TRACE(("scan %s\n", name)); 737 738 module_info* module; 739 if (get_module(name, &module) == B_OK) { 740 // we don't need the module right now, but we give it a chance 741 // to register itself 742 put_module(name); 743 } 744 } 745 } 746 747 748 status_t 749 init_stack() 750 { 751 status_t status = init_domains(); 752 if (status != B_OK) 753 return status; 754 755 status = init_interfaces(); 756 if (status != B_OK) 757 goto err1; 758 759 status = init_timers(); 760 if (status != B_OK) 761 goto err2; 762 763 status = init_notifications(); 764 if (status < B_OK) { 765 // If this fails, it just means there won't be any notifications, 766 // it's not a fatal error. 767 dprintf("networking stack notifications could not be initialized: %s\n", 768 strerror(status)); 769 } 770 771 module_info* dummy; 772 status = get_module(NET_SOCKET_MODULE_NAME, &dummy); 773 if (status != B_OK) 774 goto err3; 775 776 mutex_init(&sChainLock, "net chains"); 777 mutex_init(&sInitializeChainLock, "net intialize chains"); 778 779 sFamilies = hash_init(10, offsetof(struct family, next), 780 &family::Compare, &family::Hash); 781 if (sFamilies == NULL) { 782 status = B_NO_MEMORY; 783 goto err5; 784 } 785 786 sProtocolChains = hash_init(10, offsetof(struct chain, next), 787 &chain::Compare, &chain::Hash); 788 if (sProtocolChains == NULL) { 789 status = B_NO_MEMORY; 790 goto err6; 791 } 792 793 sDatalinkProtocolChains = hash_init(10, offsetof(struct chain, next), 794 &chain::Compare, &chain::Hash); 795 if (sDatalinkProtocolChains == NULL) { 796 status = B_NO_MEMORY; 797 goto err7; 798 } 799 800 sReceivingProtocolChains = hash_init(10, offsetof(struct chain, next), 801 &chain::Compare, &chain::Hash); 802 if (sReceivingProtocolChains == NULL) { 803 status = B_NO_MEMORY; 804 goto err8; 805 } 806 807 sInitialized = true; 808 809 link_init(); 810 scan_modules("network/protocols"); 811 scan_modules("network/datalink_protocols"); 812 813 // TODO: for now! 814 register_domain_datalink_protocols(AF_INET, IFT_LOOP, 815 "network/datalink_protocols/loopback_frame/v1", NULL); 816 register_domain_datalink_protocols(AF_INET, IFT_ETHER, 817 "network/datalink_protocols/ipv4_datagram/v1", 818 "network/datalink_protocols/arp/v1", 819 "network/datalink_protocols/ethernet_frame/v1", 820 NULL); 821 822 return B_OK; 823 824 err8: 825 hash_uninit(sDatalinkProtocolChains); 826 err7: 827 hash_uninit(sProtocolChains); 828 err6: 829 hash_uninit(sFamilies); 830 err5: 831 mutex_destroy(&sInitializeChainLock); 832 mutex_destroy(&sChainLock); 833 err3: 834 uninit_timers(); 835 err2: 836 uninit_interfaces(); 837 err1: 838 uninit_domains(); 839 return status; 840 } 841 842 843 status_t 844 uninit_stack() 845 { 846 TRACE(("Unloading network stack\n")); 847 848 put_module(NET_SOCKET_MODULE_NAME); 849 uninit_timers(); 850 uninit_interfaces(); 851 uninit_domains(); 852 uninit_notifications(); 853 854 mutex_destroy(&sChainLock); 855 mutex_destroy(&sInitializeChainLock); 856 857 // remove chains and families 858 859 chain::DeleteChains(sProtocolChains); 860 chain::DeleteChains(sDatalinkProtocolChains); 861 chain::DeleteChains(sReceivingProtocolChains); 862 863 uint32 cookie = 0; 864 while (true) { 865 struct family* family = (struct family*)hash_remove_first(sFamilies, 866 &cookie); 867 if (family == NULL) 868 break; 869 870 delete family; 871 } 872 873 hash_uninit(sProtocolChains); 874 hash_uninit(sDatalinkProtocolChains); 875 hash_uninit(sReceivingProtocolChains); 876 hash_uninit(sFamilies); 877 878 return B_OK; 879 } 880 881 882 static status_t 883 stack_std_ops(int32 op, ...) 884 { 885 switch (op) { 886 case B_MODULE_INIT: 887 return sInitialized ? B_OK : B_BUSY; 888 case B_MODULE_UNINIT: 889 return B_OK; 890 891 default: 892 return B_ERROR; 893 } 894 } 895 896 897 net_stack_module_info gNetStackModule = { 898 { 899 NET_STACK_MODULE_NAME, 900 0, 901 stack_std_ops 902 }, 903 904 register_domain, 905 unregister_domain, 906 get_domain, 907 908 register_domain_protocols, 909 register_domain_datalink_protocols, 910 register_domain_receiving_protocol, 911 912 get_domain_receiving_protocol, 913 put_domain_receiving_protocol, 914 915 register_device_deframer, 916 unregister_device_deframer, 917 register_domain_device_handler, 918 register_device_handler, 919 unregister_device_handler, 920 register_device_monitor, 921 unregister_device_monitor, 922 device_link_changed, 923 device_removed, 924 device_enqueue_buffer, 925 926 notify_socket, 927 928 checksum, 929 930 init_fifo, 931 uninit_fifo, 932 fifo_enqueue_buffer, 933 fifo_dequeue_buffer, 934 clear_fifo, 935 fifo_socket_enqueue_buffer, 936 937 init_timer, 938 set_timer, 939 cancel_timer, 940 wait_for_timer, 941 is_timer_active, 942 is_timer_running, 943 944 is_syscall, 945 is_restarted_syscall, 946 store_syscall_restart_timeout, 947 restore_syscall_restart_timeout, 948 949 create_ancillary_data_container, 950 delete_ancillary_data_container, 951 add_ancillary_data, 952 remove_ancillary_data, 953 move_ancillary_data, 954 next_ancillary_data 955 }; 956 957 module_info* modules[] = { 958 (module_info*)&gNetStackModule, 959 (module_info*)&gNetBufferModule, 960 (module_info*)&gNetSocketModule, 961 (module_info*)&gNetDatalinkModule, 962 (module_info*)&gLinkModule, 963 (module_info*)&gNetStackInterfaceModule, 964 NULL 965 }; 966