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