1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME: 80** 81** comnet.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Network Listener Service Interface. 90** 91** This file provides (1) all of the PUBLIC Network Listener Service 92** API operations, and (2) the "portable" PRIVATE service operations. 93** 94** 95** 96*/ 97 98#include <commonp.h> /* Common internals for RPC Runtime system */ 99#include <com.h> /* Externals for Common Services component */ 100#include <comprot.h> /* Externals for common Protocol Services */ 101#include <comnaf.h> /* Externals for common NAF Services */ 102#include <comp.h> /* Internals for Common Services component */ 103#include <comcthd.h> /* Externals for Call Thread sub-component */ 104#include <comnetp.h> /* Internals for Network sub-component */ 105#include <comfwd.h> /* Externals for Common Services Fwd comp */ 106#include <dce/mgmt.h> 107 108/* 109***************************************************************************** 110* 111* local data structures 112* 113***************************************************************************** 114*/ 115 116/* 117 * Miscellaneous Data Declarations 118 */ 119 120/* 121 * Data Declarations for rpc_network_inq_protseqs() 122 * 123 * Note: These are setup at initialization time 124 */ 125 126INTERNAL rpc_protseq_vector_p_t psv = NULL; /* ptr to local protseq vector */ 127INTERNAL int psv_size; /* mem alloc size for protseq vector */ 128INTERNAL int psv_str_size; /* mem alloc size for protseq strings */ 129 130#define PSV_SIZE sizeof (rpc_protseq_vector_t) + \ 131 RPC_C_PROTSEQ_MAX * (RPC_C_PROTSEQ_ID_MAX-1) 132 133/* 134 * The state of the listener thread that need to be shared across modules. 135 */ 136INTERNAL rpc_listener_state_t listener_state; 137 138/* 139 * Boolean indicating whether a thread has called "rpc_server_listen". 140 */ 141INTERNAL boolean in_server_listen; 142 143/* 144 * Condition variable signalled to shutdown "rpc_server_listen" thread. 145 */ 146INTERNAL rpc_cond_t shutdown_cond; 147INTERNAL boolean in_server_shutdown; 148 149/* 150 * Count of registered clients for idle detection. 151 */ 152INTERNAL rpc_mutex_t active_clients_mutex; 153INTERNAL volatile signed32 active_clients = 0; 154 155 156/* 157 * forward declarations of internal (static) functions 158 */ 159 160INTERNAL void bv_alloc ( 161 rpc_binding_vector_p_t /*old_vec*/, 162 rpc_binding_vector_p_t * /*new_vec*/, 163 unsigned32 * /*status*/ 164 ); 165 166/* 167**++ 168** 169** ROUTINE NAME: rpc_server_inq_bindings 170** 171** SCOPE: PUBLIC - declared in rpc.idl 172** 173** DESCRIPTION: 174** 175** Return the bindings for this server to which RPCs may be made. 176** Note that object UUIDs are not part of these bindings. 177** 178** INPUTS: none 179** 180** INPUTS/OUTPUTS: none 181** 182** OUTPUTS: 183** 184** binding_vector The vector of valid bindings to this server. 185** 186** status The result of the operation. One of: 187** rpc_s_ok 188** rpc_s_no_bindings 189** rpc_s_coding_error 190** 191** IMPLICIT INPUTS: none 192** 193** IMPLICIT OUTPUTS: none 194** 195** FUNCTION VALUE: void 196** 197** SIDE EFFECTS: none 198** 199**-- 200**/ 201 202PUBLIC void rpc_server_inq_bindings 203( 204 rpc_binding_vector_p_t *binding_vec, 205 unsigned32 *status 206) 207{ 208 unsigned int nd_index; /* network info table index */ 209 unsigned int bv_index; /* binding vector index */ 210 unsigned32 av_index; /* RPC Address vector index */ 211 rpc_binding_vector_p_t bvp, new_bvp; /* local ptr to binding vector */ 212 rpc_addr_vector_p_t addr_vec; /* rpc addrs of network desc */ 213 rpc_binding_rep_p_t binding_rep; 214 unsigned int i; 215 unsigned32 xstatus; 216 217 CODING_ERROR (status); 218 RPC_VERIFY_INIT (); 219 220 *binding_vec = NULL; /* assume the worst */ 221 222 /* 223 * Allocate up an initial binding vector. Note that we might need 224 * to allocate up a larger one later if the one we get now turns out 225 * to not be big enough 226 */ 227 bv_alloc ((rpc_binding_vector_p_t) NULL, &bvp, status); 228 229 if (*status != rpc_s_ok) 230 { 231 return; 232 } 233 234 bv_index = 0; 235 236 /* 237 * For each socket we know about... 238 */ 239 for (nd_index = 0; nd_index < listener_state.high_water; nd_index++) 240 { 241 rpc_listener_sock_p_t lsock = &listener_state.socks[nd_index]; 242 243 /* 244 * Consider only sockets that are in use and for server usage. 245 */ 246 if (lsock->busy && lsock->is_server) 247 { 248 /* 249 * Get all the RPC Addresses represented by this descriptor. 250 */ 251 rpc__naf_desc_inq_addr (lsock->protseq_id, lsock->desc, &addr_vec, status); 252 253 if (*status != rpc_s_ok) 254 { 255 break; 256 } 257 258 /* 259 * For each RPC Address... 260 */ 261 for (av_index = 0; av_index < addr_vec->len; av_index++) 262 { 263 /* 264 * If we've exceeded the size of the current vector, 265 * allocate up a new one. 266 */ 267 if (bv_index >= bvp->count) 268 { 269 bv_alloc (bvp, &new_bvp, status); 270 271 if (*status != rpc_s_ok) 272 { 273 break; 274 } 275 276 bvp = new_bvp; 277 } 278 279 /* 280 * Allocate a binding with this RPC Address. 281 */ 282 binding_rep = 283 rpc__binding_alloc (false, &uuid_g_nil_uuid, 284 lsock->protocol_id, addr_vec->addrs[av_index], status); 285 286 if (*status != rpc_s_ok) 287 { 288 break; 289 } 290 291 /* 292 * The rpc_addr reference has been handed off to the 293 * binding, make sure that it isn't freed. 294 */ 295 addr_vec->addrs[av_index] = NULL; 296 297 binding_rep->addr_is_dynamic = lsock->is_dynamic; 298 bvp->binding_h[bv_index] = (rpc_binding_handle_t) binding_rep; 299 300 bv_index++; /* bump for next binding vector entry */ 301 } 302 303 /* 304 * Free up the allocated addr vector (and any addrs that 305 * haven't been given to a binding). 306 */ 307 rpc__naf_addr_vector_free (&addr_vec, &xstatus); 308 309 /* 310 * If there was previously an error we're done. 311 */ 312 if (*status != rpc_s_ok) 313 break; 314 } 315 } 316 317 /* 318 * Return with status if there aren't any bindings. 319 */ 320 if (bv_index == 0 && *status == rpc_s_ok) 321 { 322 *status = rpc_s_no_bindings; 323 } 324 325 /* 326 * If everything went fine, return the bindings. 327 * Otherwise free resources before returning (retain the original error). 328 */ 329 if (*status == rpc_s_ok) 330 { 331 bvp->count = bv_index; 332 *binding_vec = bvp; 333 } 334 else 335 { 336 for (i = 0; i < bv_index; i++) 337 { 338 rpc_binding_free 339 ((rpc_binding_handle_t *) &bvp->binding_h[i], &xstatus); 340 } 341 342 RPC_MEM_FREE (bvp, RPC_C_MEM_BINDING_VEC); 343 *binding_vec = NULL; 344 } 345} 346 347/* 348**++ 349** 350** ROUTINE NAME: rpc_server_listen 351** 352** SCOPE: PUBLIC - declared in rpc.idl 353** 354** DESCRIPTION: 355** 356** This routine begins listening to the network for RPC requests. 357** 358** INPUTS: 359** 360** max_calls The maximum number of concurrent calls which this 361** server will process. 362** 363** INPUTS/OUTPUTS: none 364** 365** OUTPUTS: 366** 367** status The result of the operation. One of: 368** rpc_s_ok 369** rpc_s_already_listening 370** rpc_s_no_protseqs_registered 371** rpc_s_coding_error 372** 373** IMPLICIT INPUTS: none 374** 375** IMPLICIT OUTPUTS: none 376** 377** FUNCTION VALUE: void 378** 379** SIDE EFFECTS: none 380** 381**-- 382**/ 383 384PUBLIC void rpc_server_listen 385( 386 unsigned32 max_calls, 387 unsigned32 *status 388) 389{ 390 int i; 391 392 CODING_ERROR (status); 393 RPC_VERIFY_INIT (); 394 395 RPC_MUTEX_LOCK (listener_state.mutex); 396 397 /* 398 * Only one listener at a time, please. 399 */ 400 if (in_server_listen) 401 { 402 *status = rpc_s_already_listening; 403 RPC_MUTEX_UNLOCK (listener_state.mutex); 404 return; 405 } 406 407 /* 408 * See if there are any server sockets. We must add them to the real 409 * listener so it'll start select'ing on them. 410 */ 411 for (i = 0; i < listener_state.high_water; i++) 412 { 413 rpc_listener_sock_p_t lsock = &listener_state.socks[i]; 414 415 if (lsock->busy && lsock->is_server) 416 { 417 in_server_listen = true; 418 if (! lsock->is_active) 419 { 420 rpc__nlsn_activate_desc (&listener_state, i, status); 421 } 422 } 423 } 424 425 /* 426 * If we scanned the whole table and found no server sockets, there's 427 * no point being here. 428 */ 429 if (! in_server_listen) 430 { 431 *status = rpc_s_no_protseqs_registered; 432 RPC_MUTEX_UNLOCK (listener_state.mutex); 433 return; 434 } 435 436 /* 437 * Clear the status of the listener state table. 438 */ 439 listener_state.status = rpc_s_ok; 440 441 /* 442 * Fire up the cthreads. 443 */ 444 rpc__cthread_start_all (max_calls, status); 445 if (*status != rpc_s_ok) 446 { 447 RPC_MUTEX_UNLOCK (listener_state.mutex); 448 return; 449 } 450 451 RPC_DBG_PRINTF (rpc_e_dbg_general, 2, ("(rpc_server_listen) cthreads started\n")); 452 453 /* 454 * Wait until someone tells us to stop listening. 455 */ 456 DCETHREAD_TRY 457 { 458 unsigned idle_cycles = 0; 459 460 for (;;) 461 { 462 unsigned32 timeo = rpc__server_inq_idle_timeout (); 463 464 if (timeo < rpc_s_server_idle_infinite_timeout) 465 { 466 struct timespec wtime; 467 wtime.tv_sec = time(NULL) + timeo; 468 wtime.tv_nsec = 0; 469 470 RPC_COND_TIMED_WAIT (shutdown_cond, listener_state.mutex, 471 &wtime); 472 } 473 else 474 { 475 RPC_COND_WAIT (shutdown_cond, listener_state.mutex); 476 } 477 478 /* First check whether we were asked to shut down. If so, let's 479 * just do it. 480 */ 481 if (in_server_shutdown) 482 { 483 break; 484 } 485 486 /* Nope, we must have tripped an idle timeout. */ 487 if (active_clients == 0) 488 { 489 ++idle_cycles; 490 } 491 else 492 { 493 idle_cycles = 0; 494 } 495 496 if (idle_cycles > 1) 497 { 498 RPC_DBG_GPRINTF ( 499 ("(rpc_server_listen) idling out\n")); 500 break; 501 } 502 } 503 } 504 DCETHREAD_FINALLY 505 { 506 RPC_DBG_GPRINTF (("(rpc_server_listen) Shutting down...\n")); 507 508 /* 509 * Make the real listener stop listening on our server sockets now. 510 */ 511 512 for (i = 0; i < listener_state.high_water; i++) 513 { 514 rpc_listener_sock_p_t lsock = &listener_state.socks[i]; 515 516 if (lsock->busy && lsock->is_server && lsock->is_active) 517 { 518 rpc__nlsn_deactivate_desc (&listener_state, i, status); 519 } 520 } 521 522 in_server_listen = false; 523 524 /* 525 * Set return status from the value in the listener state table. 526 */ 527 *status = listener_state.status; 528 529 /* 530 * Stop all the call executors (gracefully). 531 * 532 * Unlock the listener mutex while awaiting cthread termination. 533 * Failure to do this can result in deadlock (e.g. if a cthread/RPC 534 * tries to execute a "stop listening" while we're blocked with 535 * the listener's mutex held). 536 */ 537 538 in_server_shutdown = false; 539 RPC_MUTEX_UNLOCK (listener_state.mutex); 540 541 /* 542 * Stop call threads after closing listener sockets to avoid hang 543 * if a request is received immediately after listener thread has 544 * stopped call threads (HP fix JAGad42160). 545 */ 546 rpc__cthread_stop_all (status); 547 548 RPC_DBG_PRINTF (rpc_e_dbg_general, 2, ("(rpc_server_listen) cthreads stopped\n")); 549 550 } 551 DCETHREAD_ENDTRY 552} 553 554/* 555**++ 556** 557** ROUTINE NAME: rpc__server_stop_listening 558** 559** SCOPE: PRIVATE - declared in com.h 560** 561** DESCRIPTION: 562** 563** Cause the thread that called "rpc_server_listen" to gracefully return 564** from that routine. 565** 566** INPUTS: none 567** 568** INPUTS/OUTPUTS: none 569** 570** OUTPUTS: 571** 572** status The result of the operation. 573** 574** IMPLICIT INPUTS: none 575** 576** IMPLICIT OUTPUTS: none 577** 578** FUNCTION VALUE: void 579** 580** SIDE EFFECTS: none 581** 582**-- 583**/ 584 585PRIVATE void rpc__server_stop_listening 586( 587 unsigned32 *status 588) 589{ 590 CODING_ERROR (status); 591 592 RPC_MUTEX_LOCK (listener_state.mutex); 593 594 if (! in_server_listen) 595 { 596 *status = rpc_s_not_listening; 597 RPC_MUTEX_UNLOCK (listener_state.mutex); 598 return; 599 } 600 601 in_server_shutdown = true; 602 RPC_COND_SIGNAL (shutdown_cond, listener_state.mutex); 603 604 RPC_MUTEX_UNLOCK (listener_state.mutex); 605 606 *status = rpc_s_ok; 607} 608 609/* 610**++ 611** 612** ROUTINE NAME: rpc__server_is_listening 613** 614** SCOPE: PRIVATE - declared in com.h 615** 616** DESCRIPTION: 617** 618** Return true iff there's a thread in "rpc_server_listen". 619** 620** 621** INPUTS: none 622** 623** INPUTS/OUTPUTS: none 624** 625** OUTPUTS: none 626** 627** IMPLICIT INPUTS: none 628** 629** IMPLICIT OUTPUTS: none 630** 631** FUNCTION VALUE: boolean 632** 633** SIDE EFFECTS: none 634** 635**-- 636**/ 637 638PRIVATE boolean32 rpc__server_is_listening (void) 639{ 640 /* 641 * We could lock, but there doesn't seem much point--the state could change 642 * as soon as we unlock. 643 */ 644 return (in_server_listen); 645} 646 647 648PRIVATE void rpc__server_incr_clients (void) 649{ 650 RPC_MUTEX_LOCK (active_clients_mutex); 651 ++active_clients; 652 RPC_MUTEX_UNLOCK (active_clients_mutex); 653} 654 655PRIVATE void rpc__server_decr_clients (void) 656{ 657 RPC_MUTEX_LOCK (active_clients_mutex); 658 if (active_clients) { 659 --active_clients; 660 } 661 RPC_MUTEX_UNLOCK (active_clients_mutex); 662} 663 664/* 665**++ 666** 667** ROUTINE NAME: rpc__server_set_idle_timeout 668** 669** SCOPE: PRIVATE - declared in com.h 670** 671** DESCRIPTION: 672** 673** Sets the idle period (in seconds) after which rpc_server_listen() 674** may return. 675** 676** 677** INPUTS: 678** 679** idle_secs The idle timeout in seconds. 680** 681** INPUTS/OUTPUTS: none 682** 683** OUTPUTS: 684** 685** status The result of the operation. One of: 686** rpc_s_ok 687** rpc_s_coding_error 688** 689** IMPLICIT INPUTS: none 690** 691** IMPLICIT OUTPUTS: none 692** 693** FUNCTION VALUE: void 694** 695** SIDE EFFECTS: none 696** 697**-- 698**/ 699 700PRIVATE void rpc__server_set_idle_timeout 701( 702 unsigned32 idle_secs, 703 unsigned32 *status 704) 705{ 706 707 CODING_ERROR (status); 708 RPC_VERIFY_INIT (); 709 710 /* On practically every architecture (all?), a single 32bit read or write 711 * is guaranteed to be atomic, so we don't need to lock this. 712 */ 713 listener_state.idle_timeout_secs = idle_secs; 714 *status = rpc_s_ok; 715} 716 717/* 718**++ 719** 720** ROUTINE NAME: rpc__server_inq_idle_timeout 721** 722** SCOPE: PRIVATE - declared in com.h 723** 724** DESCRIPTION: 725** 726** Returns the idle period (in seconds) after which rpc_server_listen() 727** may return. 728** 729** 730** INPUTS: none 731** 732** INPUTS/OUTPUTS: none 733** 734** OUTPUTS: none 735** 736** IMPLICIT INPUTS: none 737** 738** IMPLICIT OUTPUTS: none 739** 740** FUNCTION VALUE: void 741** 742** return - The idle timeout in seconds. 743** 744** SIDE EFFECTS: none 745** 746**-- 747**/ 748PRIVATE unsigned32 rpc__server_inq_idle_timeout (void) 749{ 750 unsigned32 idle_secs; 751 752 RPC_VERIFY_INIT (); 753 754 idle_secs = listener_state.idle_timeout_secs; 755 return idle_secs; 756} 757 758 759/* 760**++ 761** 762** ROUTINE NAME: rpc_server_use_all_protseqs 763** 764** SCOPE: PUBLIC - declared in rpc.idl 765** 766** DESCRIPTION: 767** 768** This routine tells the Common Communication Service to listen for RPCs 769** on all supported (by both the Common Communication Service and the 770** operating system) RPC Protocol Sequences. 771** 772** INPUTS: 773** 774** max_calls The maximum number of concurrent calls which this 775** server will process. 776** 777** INPUTS/OUTPUTS: none 778** 779** OUTPUTS: 780** 781** status The result of the operation. One of: 782** rpc_s_ok 783** rpc_s_coding_error 784** 785** IMPLICIT INPUTS: none 786** 787** IMPLICIT OUTPUTS: none 788** 789** FUNCTION VALUE: void 790** 791** SIDE EFFECTS: none 792** 793**-- 794**/ 795 796PUBLIC void rpc_server_use_all_protseqs 797( 798 unsigned32 max_calls, 799 unsigned32 *status 800) 801{ 802 unsigned int i; 803 rpc_protseq_vector_p_t psvp; 804 unsigned32 my_status; 805 806 CODING_ERROR (status); 807 RPC_VERIFY_INIT (); 808 809 /* 810 * Get a vector of valid protocol sequences supported by the 811 * Common Communications Service. 812 */ 813 rpc_network_inq_protseqs (&psvp, status); 814 815 if (*status != rpc_s_ok) 816 { 817 RPC_DBG_PRINTF(rpc_es_dbg_general, 1, (("inq_protseqs failed\n"))); 818 return; 819 } 820 821 /* 822 * Register each of the protocol sequences. 823 */ 824 for (i = 0; i < psvp->count; i++) 825 { 826 rpc_server_use_protseq (psvp->protseq[i], max_calls, status); 827 828 if (*status != rpc_s_ok) 829 { 830 break; 831 } 832 } 833 834 /* 835 * Something's got to be done here to see if there were any 836 * errors registering the valid protocol sequences. If there 837 * were any errors, we should de-register the ones registered, 838 * free the vector and return an error. 839 */ 840 841 /* 842 * Now free the protocol sequence vector. 843 */ 844 rpc_protseq_vector_free (&psvp, &my_status); 845} 846 847/* 848**++ 849** 850** ROUTINE NAME: rpc_server_use_protseq 851** 852** SCOPE: PUBLIC - declared in rpc.idl 853** 854** DESCRIPTION: 855** 856** This routine creates a descriptor for the desired Network Address 857** Family and adds it to the pool of descriptors being listened on. It 858** uses a dynamically assigned name for the descriptor for the Network 859** Address Family Service. 860** 861** INPUTS: 862** 863** rpc_protseq The RPC protocol sequence to be used. 864** 865** max_calls The maximum number of concurrent calls which this 866** server will process on this RPC protocol sequence. 867** 868** INPUTS/OUTPUTS: none 869** 870** OUTPUTS: 871** 872** status The result of the operation. One of: 873** rpc_s_ok 874** rpc_s_coding_error 875** 876** IMPLICIT INPUTS: none 877** 878** IMPLICIT OUTPUTS: none 879** 880** FUNCTION VALUE: void 881** 882** SIDE EFFECTS: none 883** 884**-- 885**/ 886 887PUBLIC void rpc_server_use_protseq 888( 889 unsigned_char_p_t rpc_protseq, 890 unsigned32 max_calls, 891 unsigned32 *status 892) 893{ 894 CODING_ERROR (status); 895 RPC_VERIFY_INIT (); 896 897 rpc_server_use_protseq_ep (rpc_protseq, max_calls, NULL, status); 898} 899 900/* 901**++ 902** 903** ROUTINE NAME: rpc_server_use_protseq_if 904** 905** SCOPE: PUBLIC - declared in rpc.idl 906** 907** DESCRIPTION: 908** 909** This routine is the same as rpc_server_use_protseq() except the 910** descriptor name is the name contained in the interface specification for 911** the given Network Address Family Service. 912** 913** INPUTS: 914** 915** rpc_protseq The RPC protocol sequence to be used. 916** 917** max_calls The maximum number of concurrent calls which this 918** server will process on this RPC protocol sequence. 919** 920** ifspec_h The interface specification containing the endpoint 921** to be used for this RPC protocol sequence. 922** 923** INPUTS/OUTPUTS: none 924** 925** OUTPUTS: 926** 927** status The result of the operation. One of: 928** rpc_s_ok 929** rpc_s_coding_error 930** 931** IMPLICIT INPUTS: none 932** 933** IMPLICIT OUTPUTS: none 934** 935** FUNCTION VALUE: void 936** 937** SIDE EFFECTS: none 938** 939**-- 940**/ 941 942PUBLIC void rpc_server_use_protseq_if (rpc_protseq, max_calls, ifspec_h, status) 943 944unsigned_char_p_t rpc_protseq; 945unsigned32 max_calls; 946rpc_if_handle_t ifspec_h; 947unsigned32 *status; 948 949{ 950 unsigned_char_p_t endpoint = NULL; 951 unsigned32 temp_status; 952 rpc_protseq_id_t pseq_id; 953 954 CODING_ERROR (status); 955 RPC_VERIFY_INIT (); 956 957 pseq_id = rpc__network_pseq_id_from_pseq (rpc_protseq, status); 958 if (*status != rpc_s_ok) 959 { 960 return; 961 } 962 963 rpc__if_inq_endpoint ((rpc_if_rep_p_t) ifspec_h, pseq_id, &endpoint, status); 964 965 if (*status != rpc_s_ok) 966 { 967 return; 968 } 969 970 rpc_server_use_protseq_ep (rpc_protseq, max_calls, endpoint, status); 971 rpc_string_free (&endpoint, &temp_status); 972} 973 974 975/* 976**++ 977** 978** ROUTINE NAME: rpc_server_use_all_protseqs_if 979** 980** SCOPE: PUBLIC - declared in rpc.idl 981** 982** DESCRIPTION: 983** 984** This routine tells the RPC runtime to listen for RPCs on all the 985** protocol sequences for which the specified interface has well-known 986** endpoints. 987** 988** INPUTS: 989** 990** max_calls The maximum number of concurrent calls which this 991** server will process. 992** 993** ifspec_h The interface specification containing the endpoints 994** to be used for this RPC protocol sequence. 995** 996** INPUTS/OUTPUTS: none 997** 998** OUTPUTS: 999** 1000** status The result of the operation. One of: 1001** rpc_s_ok 1002** rpc_s_coding_error 1003** 1004** IMPLICIT INPUTS: none 1005** 1006** IMPLICIT OUTPUTS: none 1007** 1008** FUNCTION VALUE: void 1009** 1010** SIDE EFFECTS: none 1011** 1012**-- 1013**/ 1014 1015PUBLIC void rpc_server_use_all_protseqs_if 1016( 1017 unsigned32 max_calls, 1018 rpc_if_handle_t ifspec_h, 1019 unsigned32 *status 1020) 1021{ 1022 unsigned int i; 1023 rpc_protseq_vector_p_t psvp; 1024 unsigned32 my_status; 1025 unsigned_char_p_t endpoint; 1026 rpc_protseq_id_t pseq_id; 1027 1028 CODING_ERROR (status); 1029 RPC_VERIFY_INIT (); 1030 1031 /* 1032 * Get a vector of valid protocol sequences supported by the 1033 * Common Communications Service. 1034 */ 1035 rpc_network_inq_protseqs (&psvp, status); 1036 1037 if (*status != rpc_s_ok) 1038 { 1039 return; 1040 } 1041 1042 /* 1043 * For each valid protocol sequence, see if the ifspec has an endpoint 1044 * for it. If it does, try to create a socket based on it. 1045 */ 1046 for (i = 0; i < psvp->count; i++) 1047 { 1048 1049 pseq_id = rpc__network_pseq_id_from_pseq (psvp->protseq[i], status); 1050 1051 if (*status != rpc_s_ok) 1052 { 1053 break; 1054 } 1055 1056 rpc__if_inq_endpoint ((rpc_if_rep_p_t) ifspec_h, pseq_id, 1057 &endpoint, status); 1058 1059 if (*status == rpc_s_endpoint_not_found) 1060 { 1061 *status = rpc_s_ok; 1062 continue; 1063 } 1064 if (*status != rpc_s_ok) 1065 { 1066 break; 1067 } 1068 1069 rpc_server_use_protseq_ep (psvp->protseq[i], max_calls, endpoint, status); 1070 1071 rpc_string_free (&endpoint, &my_status); 1072 1073 if (*status != rpc_s_ok) 1074 { 1075 break; 1076 } 1077 } 1078 1079 /* 1080 * Something's got to be done here to see if there were any 1081 * errors registering the valid protocol sequences. If there 1082 * were any errors, we should de-register the ones registered, 1083 * free the vector and return an error. 1084 */ 1085 1086 /* 1087 * Now free the protocol sequence vector. 1088 */ 1089 rpc_protseq_vector_free (&psvp, &my_status); 1090} 1091 1092/* 1093**++ 1094** 1095** ROUTINE NAME: rpc__server_register_fwd_map 1096** 1097** SCOPE: PRIVATE - declared in comfwd.h 1098** 1099** DESCRIPTION: 1100** 1101** Register a forwarding map function with the runtime. This registered 1102** function will be called by the protocol services to determine an 1103** appropriate forwarding endpoint for a received pkt that is not for 1104** any of the server's registered interfaces. 1105** 1106** INPUTS: 1107** 1108** map_fn The Forwarding Map function to be used. 1109** 1110** INPUTS/OUTPUTS: none 1111** 1112** OUTPUTS: 1113** 1114** status The result of the operation. One of: 1115** rpc_s_ok 1116** rpc_s_coding_error 1117** 1118** IMPLICIT INPUTS: none 1119** 1120** IMPLICIT OUTPUTS: none 1121** 1122** FUNCTION VALUE: void 1123** 1124** SIDE EFFECTS: none 1125** 1126**-- 1127**/ 1128 1129PRIVATE void rpc__server_register_fwd_map 1130( 1131 rpc_fwd_map_fn_t map_fn, 1132 unsigned32 *status 1133) 1134{ 1135 CODING_ERROR (status); 1136 1137 *status = rpc_s_ok; 1138 1139 rpc_g_fwd_fn = map_fn; 1140} 1141 1142 1143/* 1144**++ 1145** 1146** ROUTINE NAME: rpc_network_inq_protseqs 1147** 1148** SCOPE: PUBLIC - declared in rpc.idl 1149** 1150** DESCRIPTION: 1151** 1152** Return all protocol sequences supported by both the Common 1153** Communication Service and the operating system. 1154** 1155** INPUTS: none 1156** 1157** INPUTS/OUTPUTS: none 1158** 1159** OUTPUTS: 1160** 1161** protseq_vec The vector of RPC protocol sequences supported by 1162** this RPC runtime system. 1163** 1164** status The result of the operation. One of: 1165** rpc_s_ok 1166** rpc_s_no_protseqs 1167** rpc_s_no_memory 1168** rpc_s_coding_error 1169** 1170** IMPLICIT INPUTS: none 1171** 1172** IMPLICIT OUTPUTS: none 1173** 1174** FUNCTION VALUE: void 1175** 1176** SIDE EFFECTS: none 1177** 1178**-- 1179**/ 1180 1181PUBLIC void rpc_network_inq_protseqs (protseq_vec, status) 1182 1183rpc_protseq_vector_p_t *protseq_vec; 1184unsigned32 *status; 1185 1186{ 1187 unsigned32 psid; /* loop index into protseq id table */ 1188 unsigned_char_p_t ps; /* pointer to protseq string */ 1189 rpc_protseq_vector_p_t pvp; /* local pointer to protseq vector */ 1190 size_t len; 1191 size_t len_left; 1192 1193 CODING_ERROR (status); 1194 RPC_VERIFY_INIT (); 1195 1196 /* 1197 * Return with status if there aren't any protocol sequences. 1198 */ 1199 if (psv->count == 0) 1200 { 1201 *status = rpc_s_no_protseqs; 1202 return; 1203 } 1204 1205 /* 1206 * Mem alloc the return vector plus the required string space. 1207 */ 1208 RPC_MEM_ALLOC ( 1209 pvp, 1210 rpc_protseq_vector_p_t, 1211 psv_size + psv_str_size, 1212 RPC_C_MEM_PROTSEQ_VECTOR, 1213 RPC_C_MEM_WAITOK); 1214 1215 *protseq_vec = pvp; 1216 1217 /* 1218 * Copy the local protseq vector to the users return vector 1219 * and setup a pointer to the start of the returned strings. 1220 */ 1221 /* b_c_o_p_y ((char *) psv, (char *) pvp, psv_size); */ 1222 memmove((char *)pvp, (char *)psv, psv_size) ; 1223 ps = (unsigned_char_p_t) (((char *)pvp) + psv_size); 1224 1225 /* 1226 * Loop through the local protocol sequence id table: 1227 * - copy each protseq string to the return vector string space 1228 * - bump the string space pointer 1229 */ 1230 len_left = psv_str_size; 1231 for (psid = 0; psid < psv->count; psid++) 1232 { 1233 pvp->protseq[psid] = ps; 1234 strlcpy ((char *) ps, (char *) psv->protseq[psid], len_left); 1235 len = strlen ((char *) ps) + 1; /* includes the terminating NULL */ 1236 len_left -= len; 1237 ps += len; 1238 } 1239 1240 *status = rpc_s_ok; 1241 return; 1242} 1243 1244/* 1245**++ 1246** 1247** ROUTINE NAME: rpc_network_is_protseq_valid 1248** 1249** SCOPE: PUBLIC - declared in rpc.idl 1250** 1251** DESCRIPTION: 1252** 1253** This routine determines whether the Common Communications Service 1254** supports a given RPC Protocol Sequence. 1255** 1256** INPUTS: 1257** 1258** rpc_protseq The RPC protocol sequence whose validity is to be 1259** determined. 1260** 1261** INPUTS/OUTPUTS: none 1262** 1263** OUTPUTS: 1264** 1265** status The result of the operation. One of: 1266** rpc_s_ok 1267** rpc_s_coding_error 1268** 1269** IMPLICIT INPUTS: none 1270** 1271** IMPLICIT OUTPUTS: none 1272** 1273** FUNCTION VALUE: 1274** 1275** return - true if the protocol sequence is supported 1276** false if the protocol sequence is not supported 1277** 1278** SIDE EFFECTS: none 1279** 1280**-- 1281**/ 1282 1283PUBLIC boolean32 rpc_network_is_protseq_valid (rpc_protseq, status) 1284 1285unsigned_char_p_t rpc_protseq; 1286unsigned32 *status; 1287 1288{ 1289 CODING_ERROR (status); 1290 RPC_VERIFY_INIT (); 1291 1292 /* 1293 * Find the correct entry in the RPC Protocol Sequence ID table using the 1294 * RPC Protocol Sequence string passed in as an argument. 1295 */ 1296 (void) rpc__network_pseq_id_from_pseq (rpc_protseq, status); 1297 1298 if (*status == rpc_s_ok) 1299 { 1300 return true; 1301 } 1302 else 1303 { 1304 return false; 1305 } 1306} 1307 1308/* 1309**++ 1310** 1311** ROUTINE NAME: rpc_protseq_vector_free 1312** 1313** SCOPE: PUBLIC - declared in rpc.idl 1314** 1315** DESCRIPTION: 1316** 1317** This routine will free the RPC Protocol Sequence strings pointed to in 1318** the vector and the vector itself. 1319** 1320** Note: The service that allocates this vector (rpc_network_inq_protseqs()) 1321** mem alloc()'s the memory required for the vector in one large chunk. 1322** We therefore don't have to play any games, we just free once 1323** for the base vector pointer. 1324** 1325** INPUTS: none 1326** 1327** INPUTS/OUTPUTS: 1328** 1329** protseq_vec The vector of RPC protocol sequences to be freed. 1330** 1331** OUTPUTS: 1332** 1333** status The result of the operation. One of: 1334** rpc_s_ok 1335** rpc_s_coding_error 1336** 1337** IMPLICIT INPUTS: none 1338** 1339** IMPLICIT OUTPUTS: none 1340** 1341** FUNCTION VALUE: void 1342** 1343** SIDE EFFECTS: none 1344** 1345**-- 1346**/ 1347 1348PUBLIC void rpc_protseq_vector_free (protseq_vector, status) 1349 1350rpc_protseq_vector_p_t *protseq_vector; 1351unsigned32 *status; 1352 1353{ 1354 CODING_ERROR (status); 1355 RPC_VERIFY_INIT (); 1356 1357 RPC_MEM_FREE (*protseq_vector, RPC_C_MEM_PROTSEQ_VECTOR); 1358 1359 *protseq_vector = NULL; 1360 1361 *status = rpc_s_ok; 1362 return; 1363} 1364 1365/* 1366**++ 1367** 1368** ROUTINE NAME: rpc_network_monitor_liveness 1369** 1370** SCOPE: PUBLIC - declared in rpc.idl 1371** 1372** DESCRIPTION: 1373** 1374** This routine tells the Common Communication Service to call the routine 1375** provided if communications are lost to the process represented by the 1376** client handle provided. 1377** 1378** INPUTS: 1379** 1380** binding_h The binding on which to monitor liveness. 1381** 1382** client_handle The client for which liveness is to be monitored. 1383** 1384** rundown_fn The routine to be called if communications are lost. 1385** 1386** INPUTS/OUTPUTS: none 1387** 1388** OUTPUTS: 1389** 1390** status The result of the operation. One of: 1391** rpc_s_ok 1392** rpc_s_invalid_binding 1393** rpc_s_coding_error 1394** 1395** IMPLICIT INPUTS: none 1396** 1397** IMPLICIT OUTPUTS: none 1398** 1399** FUNCTION VALUE: void 1400** 1401** SIDE EFFECTS: none 1402** 1403**-- 1404**/ 1405 1406PUBLIC void rpc_network_monitor_liveness 1407( 1408 rpc_binding_handle_t binding_h, 1409 rpc_client_handle_t client_handle, 1410 rpc_network_rundown_fn_t rundown_fn, 1411 unsigned32 *status 1412) 1413{ 1414 rpc_protocol_id_t protid; 1415 rpc_prot_network_epv_p_t net_epv; 1416 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1417 1418 assert(binding_rep != NULL); 1419 1420 CODING_ERROR (status); 1421 RPC_VERIFY_INIT (); 1422 1423 RPC_BINDING_VALIDATE(binding_rep, status); 1424 if (*status != rpc_s_ok) 1425 return; 1426 1427 /* 1428 * Get the protocol id from the binding handle (binding_rep) 1429 */ 1430 1431 protid = binding_rep->protocol_id; 1432 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1433 1434 /* 1435 * Pass through to the network protocol routine. 1436 */ 1437 (*net_epv->network_mon) 1438 (binding_rep, client_handle, rundown_fn, status); 1439} 1440 1441/* 1442**++ 1443** 1444** ROUTINE NAME: rpc_network_stop_monitoring 1445** 1446** SCOPE: PUBLIC - declared in rpc.idl 1447** 1448** DESCRIPTION: 1449** 1450** This routine tells the Common Communication Service to cancel 1451** rpc_network_monitor_liveness. 1452** 1453** INPUTS: 1454** 1455** binding_h The binding on which to stop monitoring liveness. 1456** 1457** client_handle The client for which liveness monitoring is to be 1458** stopped. 1459** 1460** INPUTS/OUTPUTS: none 1461** 1462** OUTPUTS: 1463** 1464** status The result of the operation. One of: 1465** rpc_s_ok 1466** rpc_s_invalid_binding 1467** rpc_s_coding_error 1468** 1469** IMPLICIT INPUTS: none 1470** 1471** IMPLICIT OUTPUTS: none 1472** 1473** FUNCTION VALUE: void 1474** 1475** SIDE EFFECTS: none 1476** 1477**-- 1478**/ 1479 1480PUBLIC void rpc_network_stop_monitoring (binding_h, client_h, status) 1481 1482rpc_binding_handle_t binding_h; 1483rpc_client_handle_t client_h; 1484unsigned32 *status; 1485 1486{ 1487 rpc_protocol_id_t protid; 1488 rpc_prot_network_epv_p_t net_epv; 1489 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1490 1491 assert(binding_rep != NULL); 1492 1493 CODING_ERROR (status); 1494 RPC_VERIFY_INIT (); 1495 1496 RPC_BINDING_VALIDATE(binding_rep, status); 1497 if (*status != rpc_s_ok) 1498 return; 1499 1500 /* 1501 * Get the protocol id from the binding handle (binding_rep) 1502 */ 1503 protid = binding_rep->protocol_id; 1504 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1505 1506 /* 1507 * Pass through to the network protocol routine. 1508 */ 1509 (*net_epv->network_stop_mon) 1510 (binding_rep, client_h, status); 1511} 1512 1513/* 1514**++ 1515** 1516** ROUTINE NAME: rpc_network_maintain_liveness 1517** 1518** SCOPE: PUBLIC - declared in rpc.idl 1519** 1520** DESCRIPTION: 1521** 1522** This routine tells the Common Communication Service to actively keep 1523** communications alive with the process identified in the binding. 1524** 1525** INPUTS: 1526** 1527** binding_h The binding on which to maintain liveness. 1528** 1529** INPUTS/OUTPUTS: none 1530** 1531** OUTPUTS: 1532** 1533** status The result of the operation. One of: 1534** rpc_s_ok 1535** rpc_s_invalid_binding 1536** rpc_s_coding_error 1537** 1538** IMPLICIT INPUTS: none 1539** 1540** IMPLICIT OUTPUTS: none 1541** 1542** FUNCTION VALUE: void 1543** 1544** SIDE EFFECTS: none 1545** 1546**-- 1547**/ 1548 1549PUBLIC void rpc_network_maintain_liveness (binding_h, status) 1550 1551rpc_binding_handle_t binding_h; 1552unsigned32 *status; 1553 1554{ 1555 rpc_protocol_id_t protid; 1556 rpc_prot_network_epv_p_t net_epv; 1557 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1558 1559 assert(binding_rep != NULL); 1560 1561 CODING_ERROR (status); 1562 RPC_VERIFY_INIT (); 1563 1564 RPC_BINDING_VALIDATE(binding_rep, status); 1565 if (*status != rpc_s_ok) 1566 return; 1567 1568 /* 1569 * Get the protocol id from the binding handle (binding_rep) 1570 */ 1571 protid = binding_rep->protocol_id; 1572 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1573 1574 /* 1575 * Pass through to the network protocol routine. 1576 */ 1577 (*net_epv->network_maint) (binding_rep, status); 1578} 1579 1580/* 1581**++ 1582** 1583** ROUTINE NAME: rpc_network_stop_maintaining 1584** 1585** SCOPE: PUBLIC - declared in rpc.idl 1586** 1587** DESCRIPTION: 1588** 1589** This routine tells the Common Communication Service to cancel 1590** rpc_network_maintain_liveness. 1591** 1592** INPUTS: 1593** 1594** binding_h The binding on which to stop maintaining liveness. 1595** 1596** INPUTS/OUTPUTS: none 1597** 1598** OUTPUTS: 1599** 1600** status The result of the operation. One of: 1601** rpc_s_ok 1602** rpc_s_invalid_binding 1603** rpc_s_coding_error 1604** 1605** IMPLICIT INPUTS: none 1606** 1607** IMPLICIT OUTPUTS: none 1608** 1609** FUNCTION VALUE: void 1610** 1611** SIDE EFFECTS: none 1612** 1613**-- 1614**/ 1615 1616PUBLIC void rpc_network_stop_maintaining 1617( 1618 rpc_binding_handle_t binding_h, 1619 unsigned32 *status 1620) 1621{ 1622 rpc_protocol_id_t protid; 1623 rpc_prot_network_epv_p_t net_epv; 1624 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1625 1626 assert(binding_rep != NULL); 1627 1628 CODING_ERROR (status); 1629 RPC_VERIFY_INIT (); 1630 1631 RPC_BINDING_VALIDATE(binding_rep, status); 1632 if (*status != rpc_s_ok) 1633 return; 1634 1635 /* 1636 * Get the protocol id from the binding handle (binding_rep) 1637 */ 1638 protid = binding_rep->protocol_id; 1639 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1640 1641 /* 1642 * Pass through to the network protocol routine. 1643 */ 1644 (*net_epv->network_stop_maint) 1645 (binding_rep, status); 1646} 1647 1648/* 1649**++ 1650** 1651** ROUTINE NAME: rpc_network_close 1652** 1653** SCOPE: PUBLIC - declared in rpc.idl 1654** 1655** DESCRIPTION: 1656** 1657** This routine tells the Common Communication Service to remove 1658** any associations underlying the binding handle. 1659** 1660** INPUTS: 1661** 1662** binding_h The binding on which to close the association 1663** 1664** INPUTS/OUTPUTS: none 1665** 1666** OUTPUTS: 1667** 1668** status The result of the operation. One of: 1669** rpc_s_ok 1670** rpc_s_invalid_binding 1671** rpc_s_coding_error 1672** 1673** IMPLICIT INPUTS: none 1674** 1675** IMPLICIT OUTPUTS: none 1676** 1677** FUNCTION VALUE: void 1678** 1679** SIDE EFFECTS: none 1680** 1681**-- 1682**/ 1683 1684PUBLIC void rpc_network_close 1685( 1686 rpc_binding_handle_t binding_h, 1687 unsigned32 *status 1688) 1689{ 1690 rpc_protocol_id_t protid; 1691 rpc_prot_network_epv_p_t net_epv; 1692 rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h; 1693 1694 assert(binding_rep != NULL); 1695 1696 CODING_ERROR (status); 1697 RPC_VERIFY_INIT (); 1698 1699 RPC_BINDING_VALIDATE(binding_rep, status); 1700 if (*status != rpc_s_ok) 1701 return; 1702 1703 /* 1704 * Get the protocol id from the binding handle (binding_rep) 1705 */ 1706 protid = binding_rep->protocol_id; 1707 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (protid); 1708 1709 /* 1710 * Pass through to the network protocol routine. 1711 */ 1712 (*net_epv->network_close) 1713 (binding_rep, status); 1714} 1715 1716/* 1717**++ 1718** 1719** ROUTINE NAME: rpc__network_add_desc 1720** 1721** SCOPE: PRIVATE - declared in comnet.h 1722** 1723** DESCRIPTION: 1724** 1725** This routine adds a descriptor to the pool of descriptors being 1726** listened on. 1727** 1728** INPUTS: 1729** 1730** desc The descriptor to be added to the pool. 1731** 1732** is_server A flag indicating if this is a server descriptor. 1733** 1734** rpc_protseq_id The RPC protocol sequence by which this descriptor 1735** is used. 1736** 1737** priv_info Private info associated with this descriptor. 1738** 1739** INPUTS/OUTPUTS: none 1740** 1741** OUTPUTS: 1742** 1743** status The result of the operation. One of: 1744** rpc_s_ok 1745** rpc_s_max_descs_exceeded 1746** rpc_s_coding_error 1747** 1748** IMPLICIT INPUTS: none 1749** 1750** IMPLICIT OUTPUTS: none 1751** 1752** FUNCTION VALUE: void 1753** 1754** SIDE EFFECTS: none 1755** 1756**-- 1757**/ 1758 1759PRIVATE void rpc__network_add_desc 1760( 1761 rpc_socket_t desc, 1762 boolean32 is_server, 1763 boolean32 is_dynamic, 1764 rpc_protseq_id_t rpc_protseq_id, 1765 dce_pointer_t priv_info, 1766 unsigned32 *status 1767) 1768{ 1769 int nd, old_hiwat; 1770 rpc_listener_sock_p_t lsock; 1771 1772 CODING_ERROR (status); 1773 1774 RPC_MUTEX_LOCK (listener_state.mutex); 1775 1776 /* 1777 * See if there are any free slots in the Network Info Table. 1778 */ 1779 if (listener_state.num_desc >= RPC_C_SERVER_MAX_SOCKETS) 1780 { 1781 *status = rpc_s_max_descs_exceeded; 1782 RPC_MUTEX_UNLOCK (listener_state.mutex); 1783 return; 1784 } 1785 1786 /* 1787 * Find a free slot in the Network Info Table. 1788 */ 1789 for (nd = 0; nd < listener_state.high_water; nd++) 1790 { 1791 if (! listener_state.socks[nd].busy) 1792 { 1793 break; 1794 } 1795 } 1796 1797 lsock = &listener_state.socks[nd]; 1798 1799 /* 1800 * Place the Network descriptor, the RPC Protocol Sequence Id and the 1801 * private info pointer in this slot, bump the count of the descriptors 1802 * in the table. 1803 */ 1804 lsock->busy = true; 1805 lsock->is_server = is_server; 1806 lsock->is_dynamic = is_dynamic; 1807 lsock->is_active = false; 1808 lsock->desc = desc; 1809 lsock->protseq_id = rpc_protseq_id; 1810 lsock->priv_info = priv_info; 1811 lsock->protocol_id = RPC_PROTSEQ_INQ_PROT_ID (rpc_protseq_id); 1812 lsock->network_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (lsock->protocol_id); 1813 1814 listener_state.num_desc++; 1815 old_hiwat = listener_state.high_water; 1816 if (nd == listener_state.high_water) 1817 { 1818 listener_state.high_water++; 1819 } 1820 1821 /* 1822 * Activate the descriptor to the real listener only if 1823 * "rpc_server_listen" has been called or if this is a client socket. 1824 * (Don't want to activate server sockets until "rpc_server_listen" 1825 * is called since we don't want to get any server-related I/O until 1826 * we're really a server!) 1827 */ 1828 if (in_server_listen || ! is_server) 1829 { 1830 rpc__nlsn_activate_desc (&listener_state, nd, status); 1831 if (*status != rpc_s_ok) 1832 { 1833 lsock->busy = false; 1834 listener_state.high_water = old_hiwat; 1835 listener_state.num_desc--; 1836 } 1837 } 1838 else 1839 { 1840 *status = rpc_s_ok; 1841 } 1842 1843 RPC_MUTEX_UNLOCK (listener_state.mutex); 1844} 1845 1846/* 1847**++ 1848** 1849** ROUTINE NAME: rpc__network_remove_desc 1850** 1851** SCOPE: PRIVATE - declared in comnet.h 1852** 1853** DESCRIPTION: 1854** 1855** This routine removes a descriptor from the pool of descriptors being 1856** listened on. This routine should be called only by protocol 1857** services which are attempting to register mutiple descriptors to the 1858** pool as a result of a use_protseq call. In this case the descriptors 1859** which were previously added should be closed immediately by the 1860** protocol service and hence will not use up system resources with 1861** buffered connect requests or datagrams. 1862** 1863** INPUTS: 1864** 1865** desc The descriptor to be removed from the pool. 1866** 1867** INPUTS/OUTPUTS: none 1868** 1869** OUTPUTS: 1870** 1871** status The result of the operation. One of: 1872** rpc_s_ok 1873** rpc_s_max_descs_exceeded 1874** rpc_s_desc_not_registered 1875** rpc_s_coding_error 1876** 1877** IMPLICIT INPUTS: none 1878** 1879** IMPLICIT OUTPUTS: none 1880** 1881** FUNCTION VALUE: void 1882** 1883** SIDE EFFECTS: none 1884** 1885**-- 1886**/ 1887 1888PRIVATE void rpc__network_remove_desc 1889( 1890 rpc_socket_t desc, 1891 unsigned32 *status 1892) 1893{ 1894 int nd, found_nd, maxnd; 1895 boolean found_server_socket = false; 1896 1897 CODING_ERROR (status); 1898 1899 RPC_MUTEX_LOCK (listener_state.mutex); 1900 1901 /* 1902 * Find the slot in the Network Info Table which has the Network 1903 * descriptor given (and locate the new high water mark). 1904 */ 1905 for (nd = 0, maxnd = -1, found_nd = -1; 1906 nd < listener_state.high_water; 1907 nd++) 1908 { 1909 if (listener_state.socks[nd].busy) 1910 { 1911 if (listener_state.socks[nd].desc == desc) 1912 { 1913 found_nd = nd; 1914 } 1915 else if (listener_state.socks[nd].is_server) 1916 found_server_socket = true; 1917 1918 maxnd = nd; 1919 } 1920 } 1921 1922 if (found_nd == -1) 1923 { 1924 *status = rpc_s_desc_not_registered; 1925 RPC_MUTEX_UNLOCK (listener_state.mutex); 1926 return; 1927 } 1928 1929 /* 1930 * If we just removed the last server socket, and there's a 1931 * thread sitting in rpc_server_listen(), wake it up. 1932 */ 1933 if (! found_server_socket && in_server_listen) 1934 { 1935 listener_state.status = rpc_s_no_protseqs_registered; 1936 RPC_COND_SIGNAL (shutdown_cond, listener_state.mutex); 1937 } 1938 1939 /* 1940 * Mark the slot free, decrement the number of active slots in the table, 1941 * update the high water mark (it may be the same as before). 1942 */ 1943 listener_state.socks[found_nd].busy = false; 1944 listener_state.num_desc--; 1945 listener_state.high_water = maxnd + 1; 1946 1947 /* 1948 * Do what's necessary to convey this deletion to the listener. 1949 */ 1950 rpc__nlsn_deactivate_desc (&listener_state, found_nd, status); 1951 RPC_MUTEX_UNLOCK (listener_state.mutex); 1952} 1953 1954/* 1955**++ 1956** 1957** ROUTINE NAME: rpc__network_init 1958** 1959** SCOPE: PRIVATE - declared in com.h 1960** 1961** DESCRIPTION: 1962** 1963** Initialization for this module. 1964** 1965** INPUTS: none 1966** 1967** INPUTS/OUTPUTS: none 1968** 1969** OUTPUTS: 1970** 1971** status The result of the operation. One of: 1972** rpc_s_ok 1973** rpc_s_no_memory 1974** rpc_s_coding_error 1975** 1976** IMPLICIT INPUTS: none 1977** 1978** IMPLICIT OUTPUTS: none 1979** 1980** FUNCTION VALUE: void 1981** 1982** SIDE EFFECTS: none 1983** 1984**-- 1985**/ 1986 1987PRIVATE void rpc__network_init 1988( 1989 unsigned32 *status 1990) 1991{ 1992 int pseq_id; /* protocol sequence id/index */ 1993 1994 CODING_ERROR (status); 1995 1996 /* 1997 * Initialize our mutex. Initialize our conditional variable used 1998 * for shutdown indication. Note that the mutex covers ALL the state 1999 * in this module, not just the values in "listener_state". 2000 */ 2001 2002 RPC_MUTEX_INIT (listener_state.mutex); 2003 RPC_COND_INIT (listener_state.cond, listener_state.mutex); 2004 2005 RPC_COND_INIT (shutdown_cond, listener_state.mutex); 2006 2007 RPC_MUTEX_INIT (active_clients_mutex); 2008 rpc__server_set_idle_timeout(rpc_s_server_idle_default_timeout, status); 2009 2010 /* 2011 * Allocate a local protseq vector structure. 2012 */ 2013 RPC_MEM_ALLOC(psv, rpc_protseq_vector_p_t, PSV_SIZE, 2014 RPC_C_MEM_PROTSEQ_VECTOR, RPC_C_MEM_WAITOK); 2015 2016 psv->count = 0; /* zero out the count */ 2017 psv_size = 0; /* zero out the vector malloc size */ 2018 psv_str_size = 0; /* zero out the string malloc size */ 2019 2020 /* 2021 * Loop through the protocol sequence id table and ... 2022 * 2023 * test each protocol sequence to see if it is supported and ... 2024 * if so: 2025 * - fetch the pointer to the protseq 2026 * - bump the amount of string memory required 2027 * - bump the number of supported protseq's 2028 */ 2029 for (pseq_id = 0; pseq_id < RPC_C_PROTSEQ_ID_MAX; pseq_id++) 2030 { 2031 if (RPC_PROTSEQ_INQ_SUPPORTED (pseq_id)) 2032 { 2033 psv->protseq[psv->count] = RPC_PROTSEQ_INQ_PROTSEQ (pseq_id); 2034 psv_str_size += strlen ((char *) psv->protseq[psv->count]) + 1; 2035 psv->count++; 2036 } 2037 } 2038 /* 2039 * Figure the total amount of memory required for the return vector. 2040 */ 2041 psv_size += sizeof (rpc_protseq_vector_t) /* sizeof basic struct */ 2042 + (RPC_C_PROTSEQ_MAX * (psv->count - 1)); /* sizeof protseq ptrs */ 2043 2044 *status = rpc_s_ok; 2045} 2046 2047/* 2048**++ 2049** 2050** ROUTINE NAME: rpc__network_set_priv_info 2051** 2052** SCOPE: PRIVATE - declared in comnet.h 2053** 2054** DESCRIPTION: 2055** 2056** This routine changes the private information stored with a descriptor 2057** being listened on. 2058** 2059** INPUTS: 2060** 2061** desc The descriptor whose private info is to be set. 2062** 2063** priv_info The private info to set. 2064** 2065** INPUTS/OUTPUTS: none 2066** 2067** OUTPUTS: 2068** 2069** status The result of the operation. One of: 2070** rpc_s_ok 2071** rpc_s_desc_not_registered 2072** rpc_s_coding_error 2073** 2074** IMPLICIT INPUTS: none 2075** 2076** IMPLICIT OUTPUTS: none 2077** 2078** FUNCTION VALUE: void 2079** 2080** SIDE EFFECTS: none 2081** 2082**-- 2083**/ 2084 2085PRIVATE void rpc__network_set_priv_info 2086( 2087 rpc_socket_t desc, 2088 dce_pointer_t priv_info, 2089 unsigned32 *status 2090) 2091{ 2092 int i; 2093 2094 CODING_ERROR (status); 2095 2096 /* 2097 * scan for the entry whose descriptor matches the requested 2098 * descriptor and set the corresponding entry's private info 2099 */ 2100 2101 for (i = 0; i < listener_state.high_water; i++) 2102 { 2103 if (listener_state.socks[i].busy && listener_state.socks[i].desc == desc) 2104 { 2105 listener_state.socks[i].priv_info = priv_info; 2106 *status = rpc_s_ok; 2107 return; 2108 } 2109 } 2110 *status = rpc_s_desc_not_registered; 2111} 2112 2113/* 2114**++ 2115** 2116** ROUTINE NAME: rpc__network_inq_priv_info 2117** 2118** SCOPE: PRIVATE - declared in comnet.h 2119** 2120** DESCRIPTION: 2121** 2122** This routine returns the private information stored with the given 2123** descriptor. 2124** 2125** INPUTS: 2126** 2127** desc The descriptor whose private info is to be returned. 2128** 2129** INPUTS/OUTPUTS: none 2130** 2131** OUTPUTS: 2132** 2133** priv_info The private info stored with this descriptor. 2134** 2135** status The result of the operation. One of: 2136** rpc_s_ok 2137** rpc_s_desc_not_registered 2138** rpc_s_coding_error 2139** 2140** IMPLICIT INPUTS: none 2141** 2142** IMPLICIT OUTPUTS: none 2143** 2144** FUNCTION VALUE: void 2145** 2146** SIDE EFFECTS: none 2147** 2148**-- 2149**/ 2150 2151PRIVATE void rpc__network_inq_priv_info 2152( 2153 rpc_socket_t desc, 2154 dce_pointer_t *priv_info, 2155 unsigned32 *status 2156) 2157{ 2158 int i; 2159 2160 CODING_ERROR (status); 2161 2162 /* 2163 * scan for the entry whose descriptor matches the requested 2164 * descriptor and get the corresponding entry's private info 2165 */ 2166 2167 for (i = 0; i < listener_state.high_water; i++) 2168 { 2169 if (listener_state.socks[i].busy && listener_state.socks[i].desc == desc) 2170 { 2171 *priv_info = listener_state.socks[i].priv_info; 2172 *status = rpc_s_ok; 2173 return; 2174 } 2175 } 2176 2177 *status = rpc_s_desc_not_registered; 2178} 2179 2180 2181/* 2182**++ 2183** 2184** ROUTINE NAME: rpc__network_inq_prot_version 2185** 2186** SCOPE: PRIVATE - declared in comnet.h 2187** 2188** DESCRIPTION: 2189** 2190** Return the version number of the RPC protocol sequence requested. 2191** 2192** INPUTS: 2193** 2194** rpc_protseq_id The protocol sequence id whose architected protocol id 2195** and version number is to be returned. 2196** 2197** INPUTS/OUTPUTS: none 2198** 2199** OUTPUTS: 2200** 2201** prot_id The RPC protocol sequence protocol id. 2202** version_major The RPC protocol sequence major version number. 2203** version_minor The RPC protocol sequence minor version number. 2204** status The result of the operation. One of: 2205** rpc_s_ok 2206** rpc_s_coding_error 2207** rpc_s_invalid_rpc_protseq 2208** 2209** IMPLICIT INPUTS: none 2210** 2211** IMPLICIT OUTPUTS: none 2212** 2213** FUNCTION VALUE: void 2214** 2215** SIDE EFFECTS: none 2216** 2217**-- 2218**/ 2219 2220PRIVATE void rpc__network_inq_prot_version 2221( 2222 rpc_protseq_id_t rpc_protseq_id, 2223 unsigned8 *prot_id, 2224 unsigned32 *version_major, 2225 unsigned32 *version_minor, 2226 unsigned32 *status 2227) 2228{ 2229 rpc_protocol_id_t rpc_prot_id; 2230 rpc_prot_network_epv_p_t net_epv; 2231 2232 CODING_ERROR (status); 2233 2234 /* 2235 * Check that protocol sequence is supported by this host 2236 */ 2237 if (! RPC_PROTSEQ_INQ_SUPPORTED(rpc_protseq_id)) 2238 { 2239 *status = rpc_s_protseq_not_supported; 2240 return; 2241 } 2242 2243 rpc_prot_id = RPC_PROTSEQ_INQ_PROT_ID (rpc_protseq_id); 2244 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (rpc_prot_id); 2245 2246 (*net_epv->network_inq_prot_vers) 2247 (prot_id, version_major, version_minor, status); 2248 2249} 2250 2251/* 2252**++ 2253** 2254** ROUTINE NAME: rpc__network_protseq_id_from_protseq 2255** 2256** SCOPE: PRIVATE - declared in comnet.h 2257** 2258** DESCRIPTION: 2259** 2260** This routine searches the RPC Protocol Sequence ID table and returns 2261** the Protocol Sequence ID for the given RPC Protocol Sequence string. 2262** 2263** INPUTS: 2264** 2265** rpc_protseq The RPC protocol sequence whose id is to be returned. 2266** 2267** INPUTS/OUTPUTS: none 2268** 2269** OUTPUTS: 2270** 2271** status The result of the operation. One of: 2272** rpc_s_ok 2273** rpc_s_invalid_rpc_protseq 2274** rpc_s_protseq_not_supported 2275** rpc_s_coding_error 2276** 2277** IMPLICIT INPUTS: none 2278** 2279** IMPLICIT OUTPUTS: none 2280** 2281** FUNCTION VALUE: rpc_protocol_id_t 2282** 2283** The RPC protocol sequence id. 2284** 2285** SIDE EFFECTS: none 2286** 2287**-- 2288**/ 2289 2290PRIVATE rpc_protocol_id_t rpc__network_pseq_id_from_pseq 2291( 2292 unsigned_char_p_t rpc_protseq, 2293 unsigned32 *status 2294) 2295{ 2296 rpc_protocol_id_t pseqid; 2297 2298 CODING_ERROR (status); 2299 2300 /* 2301 * special-case the protseqs "ip" and "dds" for backwards compatibility 2302 */ 2303 if ((strcmp ((char *) rpc_protseq, "ip")) == 0) 2304 { 2305 pseqid = rpc_c_protseq_id_ncadg_ip_udp; 2306 2307 /* 2308 * Verify whether the protocol sequence ID is supported. 2309 */ 2310 if (RPC_PROTSEQ_INQ_SUPPORTED (pseqid)) 2311 { 2312 *status = rpc_s_ok; 2313 return (pseqid); 2314 } 2315 else 2316 { 2317 *status = rpc_s_protseq_not_supported; 2318 return (rpc_c_invalid_protseq_id); 2319 } 2320 } 2321 2322 if ((strcmp ((char *) rpc_protseq, "dds")) == 0) 2323 { 2324 pseqid = rpc_c_protseq_id_ncadg_dds; 2325 2326 /* 2327 * Verify whether the protocol sequence ID is supported. 2328 */ 2329 if (RPC_PROTSEQ_INQ_SUPPORTED (pseqid)) 2330 { 2331 *status = rpc_s_ok; 2332 return (pseqid); 2333 } 2334 else 2335 { 2336 *status = rpc_s_protseq_not_supported; 2337 return (rpc_c_invalid_protseq_id); 2338 } 2339 } 2340 2341 /* 2342 * The protseq is not a special case string. Check the vector of 2343 * supported protocol sequences. 2344 */ 2345 for (pseqid = 0; pseqid < RPC_C_PROTSEQ_ID_MAX; pseqid++) 2346 { 2347 if ((strcmp ((char *) rpc_protseq, 2348 (char *) RPC_PROTSEQ_INQ_PROTSEQ (pseqid))) == 0) 2349 { 2350 /* 2351 * Verify whether the protocol sequence ID is supported. 2352 */ 2353 if (RPC_PROTSEQ_INQ_SUPPORTED (pseqid)) 2354 { 2355 *status = rpc_s_ok; 2356 return (pseqid); 2357 } 2358 else 2359 { 2360 *status = rpc_s_protseq_not_supported; 2361 return (rpc_c_invalid_protseq_id); 2362 } 2363 } 2364 } 2365 2366 /* 2367 * If we got this far the protocol sequence given is not valid. 2368 *status = rpc_s_invalid_rpc_protseq; 2369 */ 2370 /* not supported or invalid; it's doesn't really matter, does it? */ 2371 *status = rpc_s_protseq_not_supported; 2372 return (rpc_c_invalid_protseq_id); 2373} 2374 2375/* 2376**++ 2377** 2378** ROUTINE NAME: rpc__network_pseq_from_pseq_id 2379** 2380** SCOPE: PRIVATE - declared in com.h 2381** 2382** DESCRIPTION: 2383** 2384** Return the protseq (string) rep for the protseq_id. 2385** 2386** This is an internal routine that needs to be relatively streamlined 2387** as it is used by the forwarding mechanism. As such we assume that 2388** the input args (created by some other runtime component) are valid. 2389** Additionally, we return a pointer to the global protseq string. If 2390** future callers of this function want to do other manipulations of 2391** the string, they can copy it to private storage. 2392** 2393** INPUTS: 2394** 2395** protseq_id A *valid* protocol sequence id. 2396** 2397** INPUTS/OUTPUTS: none 2398** 2399** OUTPUTS: 2400** 2401** protseq Pointer to the protseq_id's string rep. 2402** 2403** status The result of the operation. One of: 2404** rpc_s_ok 2405** rpc_s_coding_error 2406** 2407** IMPLICIT INPUTS: none 2408** 2409** IMPLICIT OUTPUTS: none 2410** 2411** FUNCTION VALUE: void 2412** 2413** SIDE EFFECTS: none 2414** 2415**-- 2416**/ 2417 2418PRIVATE void rpc__network_pseq_from_pseq_id 2419( 2420 rpc_protseq_id_t protseq_id, 2421 unsigned_char_p_t *protseq, 2422 unsigned32 *status 2423) 2424{ 2425 CODING_ERROR (status); 2426 2427 *protseq = RPC_PROTSEQ_INQ_PROTSEQ (protseq_id); 2428 2429 *status = rpc_s_ok; 2430 return; 2431} 2432 2433/* 2434**++ 2435** 2436** ROUTINE NAME: rpc__network_inq_local_addr 2437** 2438** SCOPE: PRIVATE - declared in com.h 2439** 2440** DESCRIPTION: 2441** 2442** Return a rpc_addr bound the local host. 2443** 2444** INPUTS: 2445** 2446** protseq_id A *valid* protocol sequence id. 2447** endpoint A endpoint string (may be NULL) 2448** 2449** INPUTS/OUTPUTS: none 2450** 2451** OUTPUTS: 2452** 2453** rpc_addr Pointer to "local host" rpc_addr. 2454** 2455** status The result of the operation. One of: 2456** rpc_s_ok 2457** rpc_s_coding_error 2458** 2459** IMPLICIT INPUTS: none 2460** 2461** IMPLICIT OUTPUTS: none 2462** 2463** FUNCTION VALUE: void 2464** 2465** SIDE EFFECTS: none 2466** 2467**-- 2468**/ 2469 2470PRIVATE void rpc__network_inq_local_addr 2471( 2472 rpc_protseq_id_t pseq_id, 2473 unsigned_char_p_t endpoint, 2474 rpc_addr_p_t *rpc_addr, 2475 unsigned32 *status 2476) 2477{ 2478 rpc_socket_error_t serr; 2479 rpc_socket_t desc; 2480 rpc_addr_vector_p_t addr_vector = NULL; 2481 boolean have_addr = false; 2482 boolean have_desc = false; 2483 boolean have_addr_vec = false; 2484 unsigned32 temp_status; 2485 2486 CODING_ERROR (status); 2487 2488 /* 2489 * Create a network descriptor for this RPC Protocol Sequence. 2490 */ 2491 serr = rpc__socket_open(pseq_id, NULL, &desc); 2492 2493 if (RPC_SOCKET_IS_ERR(serr)) 2494 { 2495 RPC_DBG_GPRINTF( 2496 ("rpc__network_inq_local_addr: cant create - serror %d\n", 2497 RPC_SOCKET_ETOI(serr))); 2498 *status = rpc_s_cant_create_sock; 2499 goto CLEANUP; 2500 } 2501 have_desc = true; 2502 2503 /* 2504 * Allocate and initialized an rpc_addr which contains the necessary 2505 * info for the subsequent rpc__socket_bind() call. 2506 */ 2507 rpc__naf_addr_alloc ( 2508 pseq_id, 2509 RPC_PROTSEQ_INQ_NAF_ID (pseq_id), 2510 (unsigned_char_p_t) NULL, /* dynamic endpoint */ 2511 (unsigned_char_p_t) NULL, /* netaddr */ 2512 (unsigned_char_p_t) NULL, /* netoptions */ 2513 rpc_addr, 2514 status); 2515 2516 if (*status != rpc_s_ok) 2517 { 2518 goto CLEANUP; 2519 } 2520 have_addr = true; 2521 2522 /* 2523 * Bind the socket (Network descriptor) to the (dynamic) RPC address. 2524 */ 2525 serr = rpc__socket_bind(desc, *rpc_addr); 2526 2527 if (RPC_SOCKET_IS_ERR(serr)) 2528 { 2529 RPC_DBG_GPRINTF( 2530 ("rpc__network_inq_local_addr: cant bind - serror %d\n", 2531 RPC_SOCKET_ETOI(serr))); 2532 *status = rpc_s_cant_bind_sock; 2533 goto CLEANUP; 2534 } 2535 2536 /* 2537 * Determine a local address associated with the descriptor. 2538 */ 2539 rpc__naf_desc_inq_addr (pseq_id, desc, &addr_vector, status); 2540 2541 if (*status != rpc_s_ok) 2542 { 2543 goto CLEANUP; 2544 } 2545 have_addr_vec = true; 2546 2547 if (addr_vector->len == 0) 2548 { 2549 *status = rpc_s_no_addrs; 2550 goto CLEANUP; 2551 } 2552 2553 /* 2554 * Update the rpc_addr with the (still dynamic) local addr. 2555 */ 2556 rpc__naf_addr_overcopy (addr_vector->addrs[0], rpc_addr, status); 2557 2558 if (*status != rpc_s_ok) 2559 { 2560 goto CLEANUP; 2561 } 2562 2563 /* 2564 * Now set the endpoint. 2565 */ 2566 rpc__naf_addr_set_endpoint(endpoint, rpc_addr, status); 2567 2568 if (*status != rpc_s_ok) 2569 { 2570 goto CLEANUP; 2571 } 2572 2573 *status = rpc_s_ok; 2574 2575CLEANUP: 2576 2577 if (have_desc) 2578 (void) RPC_SOCKET_CLOSE(desc); 2579 2580 if (have_addr_vec) 2581 rpc__naf_addr_vector_free (&addr_vector, &temp_status); 2582 2583 if (*status != rpc_s_ok && have_addr) 2584 rpc__naf_addr_free(rpc_addr, &temp_status); 2585 2586 return; 2587} 2588 2589 2590/* 2591**++ 2592** 2593** ROUTINE NAME: rpc_server_use_protseq_ep 2594** 2595** SCOPE: PUBLIC - declared in rpc.idl 2596** 2597** DESCRIPTION: 2598** 2599** Register an RPC protocol sequence for use by the runtime. 2600** 2601** INPUTS: 2602** 2603** rpc_protseq The RPC protocol sequence to be registered. 2604** 2605** max_calls The maximum number of concurrent calls to be 2606** allowed for this protocol sequence. 2607** 2608** endpoint The endpoint to be used for this protocol sequence. 2609** 2610** INPUTS/OUTPUTS: none 2611** 2612** OUTPUTS: 2613** 2614** status The result of the operation. One of: 2615** rpc_s_ok 2616** rpc_s_cant_create_sock 2617** rpc_s_no_memory 2618** rpc_s_cant_bind_sock 2619** rpc_s_coding_error 2620** rpc_s_invalid_endpoint_format 2621** 2622** IMPLICIT INPUTS: none 2623** 2624** IMPLICIT OUTPUTS: none 2625** 2626** FUNCTION VALUE: void 2627** 2628** SIDE EFFECTS: none 2629** 2630**-- 2631**/ 2632 2633PUBLIC void rpc_server_use_protseq_ep 2634( 2635 unsigned_char_p_t rpc_protseq, 2636 unsigned32 max_calls, 2637 unsigned_char_p_t endpoint, 2638 unsigned32 *status 2639) 2640{ 2641 rpc_protseq_id_t pseq_id; 2642 rpc_naf_id_t naf_id; 2643 rpc_protocol_id_t prot_id; 2644 rpc_prot_network_epv_p_t net_epv; 2645 rpc_naf_epv_p_t naf_epv; 2646 unsigned32 temp_status; 2647 rpc_addr_p_t rpc_addr; 2648 unsigned_char_p_t endpoint_copy; 2649 size_t count; 2650 2651 CODING_ERROR (status); 2652 RPC_VERIFY_INIT (); 2653 2654 RPC_DBG_PRINTF(rpc_es_dbg_general, 1, ("use_protseq %s[%s]\n", rpc_protseq, endpoint)); 2655 2656 /* 2657 * Until both protocol services fully implement this argument, we'll 2658 * ignore the value provided and use the default instead. 2659 */ 2660 max_calls = rpc_c_protseq_max_reqs_default; 2661 2662 /* 2663 * Find the correct entry in the RPC Protocol Sequence ID table using the 2664 * RPC Protocol Sequence string passed in as an argument. 2665 */ 2666 pseq_id = rpc__network_pseq_id_from_pseq (rpc_protseq, status); 2667 if (*status != rpc_s_ok) 2668 { 2669 return; 2670 } 2671 2672 /* 2673 * Make a copy of the endpoint, removing unwanted escape chars. 2674 */ 2675 endpoint_copy = NULL; 2676 2677 if (endpoint != NULL) 2678 { 2679 count = strlen ((char*) endpoint); 2680 RPC_MEM_ALLOC ( 2681 endpoint_copy, 2682 unsigned_char_p_t, 2683 count + 1, 2684 RPC_C_MEM_STRING, 2685 RPC_C_MEM_WAITOK); 2686 /* fixed by lukeh - escaping was not terminating correctly */ 2687 memset(endpoint_copy, 0, count + 1); 2688 2689 /* 2690 * copy the string, filtering out escape chars 2691 */ 2692 { 2693 unsigned int i; 2694 unsigned_char_p_t p1, p2; 2695 for (i = 0, p1 = endpoint_copy, p2 = endpoint; 2696 i < count; 2697 i++, p2++) 2698 { 2699#if 0 2700 if (*p2 != '\\') 2701 { 2702 *p1++ = *p2; 2703 } 2704 /* 2705 * Copy escaped escapes, i.e., "\\" ==> "\" 2706 */ 2707 else if (((count - i) > 1) && (p2[1] == '\\')) 2708 { 2709 *p1++ = *p2; 2710 } 2711#else 2712 *p1++ = *p2; 2713#endif 2714 } 2715 } 2716 endpoint_copy[count] = '\0'; 2717 } 2718 2719 /* 2720 * Call the rpc__naf_addr_alloc() through the Network Address Family EPV 2721 * with the RPC Protocol Sequence ID, the Network Address Family ID, an 2722 * endpoint and all other fields set to NULL. This will return an 2723 * initialized rpc_addr which contains the necessary info for the 2724 * subsequent rpc__socket_bind() call (in the protocol service's 2725 * network_use_protseq function). 2726 */ 2727 naf_id = RPC_PROTSEQ_INQ_NAF_ID (pseq_id); 2728 naf_epv = RPC_NAF_INQ_EPV (naf_id); /* pointer to the epv */ 2729 2730 (*naf_epv->naf_addr_alloc) ( 2731 pseq_id, /* in - protocol sequence id */ 2732 naf_id, /* in - network address family id */ 2733 endpoint_copy, /* in - endpoint address (pointer) */ 2734 (unsigned_char_p_t) NULL, /* in - network address (pointer) */ 2735 (unsigned_char_p_t) NULL, /* in - network options (pointer) */ 2736 &rpc_addr, /* out - rpc address (pointer) */ 2737 status); /* out - status (pointer) */ 2738 2739 if (*status != rpc_s_ok) 2740 { 2741 rpc_string_free (&endpoint_copy, &temp_status); 2742 return; 2743 } 2744 2745 /* 2746 * Find the Network EPV in the RPC Protocol table using the RPC 2747 * Protocol ID found in the RPC Protocol Sequence ID table entry. 2748 */ 2749 prot_id = RPC_PROTSEQ_INQ_PROT_ID (pseq_id); 2750 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (prot_id); 2751 2752 /* 2753 * Call the protocol service to do the real work of creating the 2754 * socket(s), setting them up right, and adding them (via calls 2755 * to rpc__network_add_desc). 2756 */ 2757 (*net_epv->network_use_protseq) 2758 (pseq_id, max_calls, rpc_addr, endpoint_copy, status); 2759 2760 /* 2761 * Free the rpc_addr we allocated above. 2762 */ 2763 (*naf_epv->naf_addr_free)(&rpc_addr, &temp_status); 2764 2765 if (endpoint_copy != NULL) 2766 { 2767 rpc_string_free (&endpoint_copy, &temp_status); 2768 } 2769} 2770 2771/* 2772**++ 2773** 2774** ROUTINE NAME: rpc_server_use_protseq_socket 2775** 2776** SCOPE: PUBLIC - declared in rpc.idl 2777** 2778** DESCRIPTION: 2779** 2780** Register an RPC protocol sequence for a previously created native socket. 2781** 2782** INPUTS: 2783** 2784** rpc_protseq The RPC protocol sequence to be registered. 2785** 2786** max_calls The maximum number of concurrent calls to be 2787** allowed for this protocol sequence. 2788** 2789** sockrep A pointer to a native socket representation 2790** of the type given by rpc_protseq. 2791** 2792** INPUTS/OUTPUTS: none 2793** 2794** OUTPUTS: 2795** 2796** status The result of the operation. One of: 2797** rpc_s_ok 2798** rpc_s_no_memory 2799** rpc_s_coding_error 2800** rpc_s_invalid_rpc_protseq 2801** rpc_s_protseq_not_supported 2802** 2803** IMPLICIT INPUTS: none 2804** 2805** IMPLICIT OUTPUTS: none 2806** 2807** FUNCTION VALUE: void 2808** 2809** SIDE EFFECTS: none 2810** 2811**-- 2812**/ 2813extern void rpc_server_use_protseq_socket 2814( 2815 unsigned_char_p_t rpc_protseq, 2816 unsigned32 max_calls, 2817 void *sockrep, 2818 unsigned32 *status 2819) 2820{ 2821 rpc_protseq_id_t pseq_id; 2822 rpc_protocol_id_t prot_id; 2823 rpc_prot_network_epv_p_t net_epv; 2824 rpc_socket_t rpc_sock; 2825 rpc_socket_error_t serr; 2826 2827 CODING_ERROR (status); 2828 RPC_VERIFY_INIT (); 2829 2830 RPC_DBG_PRINTF (rpc_es_dbg_general, 1, ("use_protseq_socket %s\n", rpc_protseq)); 2831 2832 /* Find the correct entry in the RPC Protocol Sequence ID table using the 2833 * RPC Protocol Sequence string passed in as an argument. 2834 */ 2835 pseq_id = rpc__network_pseq_id_from_pseq (rpc_protseq, status); 2836 if (*status != rpc_s_ok) 2837 { 2838 return; 2839 } 2840 2841 if (!RPC_PROTSEQ_INQ_SUPPORTED (pseq_id)) 2842 { 2843 *status = rpc_s_protseq_not_supported; 2844 return; 2845 } 2846 2847 /* Duplicate the native socket representation. It's up to the client to 2848 * decide whether or not it still wants the original socket. 2849 */ 2850 serr = rpc__socket_duplicate (pseq_id, sockrep, &rpc_sock); 2851 2852 if (RPC_SOCKET_IS_ERR (serr)) 2853 { 2854 RPC_DBG_GPRINTF ( 2855 ("rpc_server_use_protseq_socket: can't create - serror %d\n", 2856 RPC_SOCKET_ETOI (serr))); 2857 *status = rpc_s_cant_create_sock; 2858 return; 2859 } 2860 2861 rpc__socket_set_close_on_exec (rpc_sock); 2862 2863 /* Find the Network EPV in the RPC Protocol table using the RPC 2864 * Protocol ID found in the RPC Protocol Sequence ID table entry. 2865 */ 2866 prot_id = RPC_PROTSEQ_INQ_PROT_ID (pseq_id); 2867 net_epv = RPC_PROTOCOL_INQ_NETWORK_EPV (prot_id); 2868 2869 /* Call the protocol service to do the real work of creating the 2870 * socket(s), setting them up right, and adding them (via calls 2871 * to rpc__network_add_desc). Note that protocols are not 2872 * required to support using a pre-made socket. 2873 */ 2874 2875 if (net_epv->network_use_socket == NULL) 2876 { 2877 (void) RPC_SOCKET_CLOSE (rpc_sock); 2878 *status = rpc_s_protocol_error; 2879 return; 2880 } 2881 2882 /* Ignore max_calls because rpc_server_use_protseq_ep() does. */ 2883 max_calls = rpc_c_protseq_max_reqs_default; 2884 2885 (*net_epv->network_use_socket) (rpc_sock, max_calls, status); 2886 2887 if (*status != rpc_s_ok) 2888 { 2889 (void) RPC_SOCKET_CLOSE (rpc_sock); 2890 return; 2891 } 2892 2893 *status = rpc_s_ok; 2894 return; 2895} 2896 2897 2898/* 2899**++ 2900** 2901** ROUTINE NAME: bv_alloc 2902** 2903** SCOPE: INTERNAL - declared locally 2904** 2905** DESCRIPTION: 2906** 2907** Allocate a binding vector. If "old_vec" is non-NULL, copy its contents 2908** into the newly allocated vector. 2909** 2910** INPUTS: 2911** 2912** old_vec The source binding vector (optional). 2913** 2914** INPUTS/OUTPUTS: none 2915** 2916** OUTPUTS: 2917** 2918** new_vec The binding vector to be created. 2919** 2920** status The result of the operation. One of: 2921** rpc_s_ok 2922** rpc_s_no_memory 2923** rpc_s_coding_error 2924** 2925** IMPLICIT INPUTS: none 2926** 2927** IMPLICIT OUTPUTS: none 2928** 2929** FUNCTION VALUE: void 2930** 2931** SIDE EFFECTS: none 2932** 2933**-- 2934**/ 2935 2936#define BINDING_VEC_INCR_LEN 1 2937 2938INTERNAL void bv_alloc (old_vec, new_vec, status) 2939 2940rpc_binding_vector_p_t old_vec; 2941rpc_binding_vector_p_t *new_vec; 2942unsigned32 *status; 2943 2944{ 2945 rpc_binding_vector_p_t bvp; 2946 int bv_size; /* sizeof the binding vector */ 2947 int i; 2948 int new_count, old_count; 2949 2950 CODING_ERROR (status); 2951 2952 *new_vec = NULL; /* assume the worst */ 2953 2954 old_count = (old_vec == NULL) ? 0 : old_vec->count; 2955 new_count = old_count + BINDING_VEC_INCR_LEN; 2956 2957 /* 2958 * Allocate up a vector to hold bindings. We don't know how many 2959 * bindings we're going to end up with, so this is only a guess. 2960 * we may need to realloc later. 2961 */ 2962 bv_size = sizeof (rpc_binding_vector_t) /* sizeof basic struct */ 2963 + sizeof (handle_t) * (new_count - 1); /* sizeof binding */ 2964 2965 /* 2966 * Allocate the vector. 2967 */ 2968 RPC_MEM_ALLOC(bvp, rpc_binding_vector_p_t, bv_size, 2969 RPC_C_MEM_BINDING_VEC, RPC_C_MEM_WAITOK); 2970 2971 bvp->count = new_count; 2972 2973 /* 2974 * Copy the old vector's contents and then free it. 2975 * NULL out unused entries. 2976 */ 2977 for (i = 0; i < old_count; i++) 2978 { 2979 bvp->binding_h[i] = old_vec->binding_h[i]; 2980 } 2981 2982 if (old_vec != NULL) 2983 { 2984 RPC_MEM_FREE (old_vec, RPC_C_MEM_BINDING_VEC); 2985 } 2986 2987 for (i = old_count; i < new_count; i++) 2988 { 2989 bvp->binding_h[i] = NULL; 2990 } 2991 2992 *new_vec = bvp; 2993 *status = rpc_s_ok; 2994} 2995 2996#ifdef ATFORK_SUPPORTED 2997/* 2998**++ 2999** 3000** ROUTINE NAME: rpc__network_fork_handler 3001** 3002** SCOPE: PRIVATE - declared in com.h 3003** 3004** DESCRIPTION: 3005** 3006** Initializes this module. 3007** 3008** INPUTS: stage The stage of the fork we are 3009** currently handling. 3010** 3011** INPUTS/OUTPUTS: none 3012** 3013** OUTPUTS: none 3014** 3015** IMPLICIT INPUTS: none 3016** 3017** IMPLICIT OUTPUTS: none 3018** 3019** FUNCTION VALUE: void 3020** 3021** SIDE EFFECTS: none 3022** 3023**-- 3024**/ 3025 3026PRIVATE void rpc__network_fork_handler 3027( 3028 rpc_fork_stage_id_t stage 3029) 3030{ 3031 switch ((int)stage) 3032 { 3033 case RPC_C_PREFORK: 3034 rpc__nlsn_fork_handler(&listener_state, stage); 3035 break; 3036 case RPC_C_POSTFORK_CHILD: 3037 /* 3038 * Reset the listener_state table to 0's. 3039 */ 3040 /*b_z_e_r_o((char *)&listener_state, sizeof(listener_state));*/ 3041 memset( &listener_state, 0, sizeof listener_state ); 3042 /* 3043 * Reset the global forwarding map function variable. 3044 */ 3045 rpc_g_fwd_fn = NULL; 3046 /* fall through */ 3047 case RPC_C_POSTFORK_PARENT: 3048 rpc__nlsn_fork_handler(&listener_state, stage); 3049 break; 3050 } 3051} 3052#endif 3053