1/*
2 * Copyright (c) 2010-2011 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**      combind.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  Definition of the Binding Services for the Common Communication
90**  Services component. These routines are called by applications to
91**  manipulate Binding Rep data structures required by the runtime.
92**
93**
94*/
95
96#include <commonp.h>    /* Common declarations for all RPC runtime */
97#include <com.h>        /* Common communications services */
98#include <comp.h>       /* Private communications services */
99#include <cs_s.h>	/* I18N codesets definitions */
100#include <comtwrflr.h>
101
102
103/*
104**++
105**
106**  ROUTINE NAME:       rpc__binding_free
107**
108**  SCOPE:              PRIVATE - declared in com.h
109**
110**  DESCRIPTION:
111**
112**  This routine will really free the Binding Rep memory - this routine
113**  should not be called directly; RPC_BINDING_RELEASE() should be used.
114**  Since a Binding Rep's size is RPC Protocol Service-specific the RPC
115**  Protocol Service is called to do the actual free.
116**
117**  INPUTS:
118**
119**      binding_rep     The binding rep pointer which points to the binding
120**                      rep data structure to be freed.
121**
122**  INPUTS/OUTPUTS:     none
123**
124**  OUTPUTS:
125**
126**      status          A value indicating the status of the routine.
127**
128**          rpc_s_ok        The call was successful.
129**
130**  IMPLICIT INPUTS:    none
131**
132**  IMPLICIT OUTPUTS:   none
133**
134**  FUNCTION VALUE:     void
135**
136**  SIDE EFFECTS:       none
137**
138**--
139**/
140
141PRIVATE void rpc__binding_free
142(
143  rpc_binding_rep_p_t     *binding_rep_p,
144  unsigned32              *status
145)
146{
147    rpc_binding_rep_p_t     binding_rep = *binding_rep_p;
148    unsigned32		    temp_status = rpc_s_ok;
149    rpc_cs_method_eval_p_t  method_p ATTRIBUTE_UNUSED;
150    rpc_cs_tags_eval_p_t    tags_p ATTRIBUTE_UNUSED;
151
152    CODING_ERROR (status);
153
154    /*
155     * The handle must be locked so that we can "atomically"
156     * free it.
157     */
158    RPC_LOCK_ASSERT(0);
159
160    /*
161     * see if an RPC address exists in this binding
162     */
163    if (binding_rep->rpc_addr != NULL)
164    {
165        /*
166         * if so, ask the NAF extension service to free the RPC address
167         */
168        (*rpc_g_naf_id[binding_rep->rpc_addr->sa.family].epv
169            ->naf_addr_free) (&(binding_rep->rpc_addr), status);
170        if (*status != rpc_s_ok) return;
171    }
172
173    /*
174     * see if we have a protocol version
175     */
176    if (binding_rep->protocol_version != NULL)
177    {
178        rpc__binding_prot_version_free(&(binding_rep->protocol_version));
179    }
180
181#ifdef PD_BUILD
182    /*
183     * check code sets I14Y
184     */
185    if (binding_rep->extended_bind_flag == RPC_C_BH_EXTENDED_CODESETS)
186    {
187	/* Release codesets relating binding information.
188	 * Determine the data structure
189	 */
190	switch (binding_rep->cs_eval.key)
191	{
192	case RPC_CS_EVAL_METHOD:
193		method_p = &binding_rep->cs_eval.tagged_union.method_key;
194
195		if (method_p->server != NULL)
196			rpc_ns_mgmt_free_codesets (
197				&(method_p->server),
198				&temp_status );
199
200		if (method_p->client != NULL)
201			rpc_ns_mgmt_free_codesets (
202				&(method_p->client),
203				&temp_status );
204		break;
205
206	case RPC_CS_EVAL_TAGS:
207
208		break;
209
210	default:
211		temp_status = rpc_s_ss_invalid_codeset_tag;
212		break;
213	}
214    }
215#endif
216
217    /*
218     * if we have any authentication info, free it up now.
219     */
220    rpc__auth_info_binding_release(binding_rep);
221
222    /*
223     * if we have transport information, free it up now
224     */
225    if (binding_rep->transport_info)
226    {
227        rpc__transport_info_release(binding_rep->transport_info);
228    }
229
230    /*
231     * Free the name service-specific part of the binding.
232     */
233    if (binding_rep->ns_specific != NULL)
234        (*rpc_g_ns_specific_free_fn) (&binding_rep->ns_specific);
235
236    /*
237     * then ask the protocol service to free the binding rep and
238     * NULL the reference.
239     */
240    (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
241        ->binding_free) (binding_rep_p, status);
242
243    if ((temp_status != rpc_s_ok) && (*status == rpc_s_ok))
244	*status = temp_status;
245}
246
247
248/*
249**++
250**
251**  ROUTINE NAME:       rpc_binding_free
252**
253**  SCOPE:              PUBLIC - declared in rpc.idl
254**
255**  DESCRIPTION:
256**
257**  This routine will release the reference on the Binding Rep and free
258**  the rep when no more references exist.  A NULL pointer will be
259**  returned.  Most runtime internal operations that want to release a binding
260**  handle reference should probably use RPC_BINDING_RELEASE(), not this
261**  routine.
262**
263**  INPUTS:             none
264**
265**  INPUTS/OUTPUTS:
266**
267**      binding_h       The binding handle which points to the binding
268**                      rep data structure to be freed.
269**
270**  OUTPUTS:
271**
272**      status          A value indicating the status of the routine.
273**
274**          rpc_s_ok        The call was successful.
275**          rpc_s_invalid_binding
276**                          RPC Protocol ID in binding handle was invalid.
277**          rpc_s_coding_error
278**
279**  IMPLICIT INPUTS:    none
280**
281**  IMPLICIT OUTPUTS:   none
282**
283**  FUNCTION VALUE:     void
284**
285**  SIDE EFFECTS:       none
286**
287**--
288**/
289
290PUBLIC void rpc_binding_free
291(
292  rpc_binding_handle_t    *binding_h,
293  unsigned32              *status
294)
295{
296    rpc_binding_rep_p_t     binding_rep = (rpc_binding_rep_p_t) *binding_h;
297
298    assert(binding_rep != NULL);
299
300    CODING_ERROR (status);
301    RPC_VERIFY_INIT ();
302
303    RPC_BINDING_VALIDATE_CLIENT(binding_rep, status);
304    if (*status != rpc_s_ok)
305        return;
306
307    /*
308     * We need to lock the handle so that we can "atomically"
309     * release it.
310     */
311    RPC_LOCK(0);
312
313    /*
314     * Release and NULL the reference (possibly free the handle).
315     */
316    RPC_BINDING_RELEASE((rpc_binding_rep_p_t *) binding_h, status);
317
318    RPC_UNLOCK(0);
319}
320
321/*
322**++
323**
324**  ROUTINE NAME:       rpc_binding_vector_free
325**
326**  SCOPE:              PUBLIC - declared in rpc.idl
327**
328**  DESCRIPTION:
329**
330**  This routine will free the Binding Rep pointed to by each non-NULL
331**  entry in the vector array. The vector memory itself is then freed.
332**
333**  INPUTS:             none
334**
335**  INPUTS/OUTPUTS:
336**
337**      binding_vec     A vector of pointers to binding rep structures.
338**
339**  OUTPUTS:
340**
341**      status          A value indicating the status of the routine.
342**
343**          rpc_s_ok        The call was successful.
344**          rpc_s_coding_error
345**          rpc_s_invalid_arg
346**
347**  IMPLICIT INPUTS:    none
348**
349**  IMPLICIT OUTPUTS:   none
350**
351**  FUNCTION VALUE:     void
352**
353**  SIDE EFFECTS:       none
354**
355**--
356**/
357
358PUBLIC void rpc_binding_vector_free
359(
360  rpc_binding_vector_p_t  *binding_vec,
361  unsigned32              *status
362)
363{
364    unsigned32              i;
365
366    CODING_ERROR (status);
367    RPC_VERIFY_INIT ();
368
369    /*
370     * check to see if binding_vec is NULL, and if so,
371     * return with an error status
372     */
373    if (binding_vec == NULL)
374    {
375        *status = rpc_s_invalid_arg;
376        return;
377    }
378
379    /*
380     * free each element in the vector array (that's non-NULL)
381     */
382    for (i = 0; i < (*binding_vec)->count; i++)
383    {
384        if ((*binding_vec)->binding_h[i] != NULL)
385        {
386            rpc_binding_free (&(*binding_vec)->binding_h[i], status);
387            if (*status != rpc_s_ok) return;
388        }
389    }
390
391    /*
392     * now free the vector memory itself
393     */
394    RPC_MEM_FREE (*binding_vec, RPC_C_MEM_BINDING_VEC);
395
396    *binding_vec = NULL;
397
398    *status = rpc_s_ok;
399}
400
401/*
402**++
403**
404**  ROUTINE NAME:       rpc_binding_set_object
405**
406**  SCOPE:              PUBLIC - declared in rpc.idl
407**
408**  DESCRIPTION:
409**
410**  This routine will set the object UUID field in the Binding Rep to the
411**  object UUID given. The RPC Protocol Service identified by the RPC
412**  Protocol ID in the Binding Rep will be notified that the Binding Rep
413**  has changed.
414**
415**  INPUTS:
416**
417**      binding_h       The binding handle which points to the binding
418**                      rep data structure to be modified.
419**
420**      object_uuid     The unique identifier of an object to which an RPC
421**                      may be made.
422**
423**  INPUTS/OUTPUTS:     none
424**
425**  OUTPUTS:
426**
427**      status          A value indicating the status of the routine.
428**
429**          rpc_s_ok        The call was successful.
430**          rpc_s_invalid_binding
431**                          RPC Protocol ID in binding handle was invalid.
432**          rpc_s_coding_error
433**
434**  IMPLICIT INPUTS:    none
435**
436**  IMPLICIT OUTPUTS:   none
437**
438**  FUNCTION VALUE:     void
439**
440**  SIDE EFFECTS:       none
441**
442**--
443**/
444
445PUBLIC void rpc_binding_set_object
446(
447    rpc_binding_handle_t    binding_h,
448    uuid_p_t                object_uuid,
449    unsigned32              *status
450)
451{
452    rpc_binding_rep_p_t     binding_rep = (rpc_binding_rep_p_t) binding_h;
453
454    assert(binding_rep != NULL);
455
456    CODING_ERROR (status);
457    RPC_VERIFY_INIT ();
458
459    RPC_BINDING_VALIDATE_CLIENT(binding_rep, status);
460    if (*status != rpc_s_ok)
461        return;
462
463    /*
464     * copy the new object UUID into the binding rep
465     * (note: a NULL object uuid pointer is treated as a nil uuid)
466     */
467    if (object_uuid != NULL)
468    {
469        binding_rep->obj = *object_uuid;
470    }
471    else
472    {
473        uuid_create_nil (&(binding_rep->obj), status);
474    }
475
476    /*
477     * notify the protocol service that the binding has changed
478     */
479    (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
480        ->binding_changed) (binding_rep, status);
481}
482
483/*
484**++
485**
486**  ROUTINE NAME:       rpc_binding_inq_object
487**
488**  SCOPE:              PUBLIC - declared in rpc.idl
489**
490**  DESCRIPTION:
491**
492**  This routine will inquire what the object UUID is in a Binding Rep.
493**
494**  INPUTS:
495**
496**      binding_h       The binding handle which points to the binding
497**                      rep data structure to be read.
498**
499**  INPUTS/OUTPUTS:     none
500**
501**  OUTPUTS:
502**
503**      object_uuid     The unique identifier of an object to which an RPC
504**                      may be made.
505**
506**      status          A value indicating the status of the routine.
507**
508**          rpc_s_ok        The call was successful.
509**          rpc_s_invalid_binding
510**                          RPC Protocol ID in binding handle was invalid.
511**          rpc_s_coding_error
512**
513**  IMPLICIT INPUTS:    none
514**
515**  IMPLICIT OUTPUTS:   none
516**
517**  FUNCTION VALUE:     void
518**
519**  SIDE EFFECTS:       none
520**
521**--
522**/
523
524PUBLIC void rpc_binding_inq_object
525(
526    rpc_binding_handle_t    binding_h,
527    idl_uuid_t                  *object_uuid,
528    unsigned32              *status
529)
530{
531    rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h;
532
533    assert(binding_rep != NULL);
534
535    CODING_ERROR (status);
536    RPC_VERIFY_INIT ();
537
538    RPC_BINDING_VALIDATE(binding_rep, status);
539    if (*status != rpc_s_ok)
540        return;
541
542    *object_uuid = binding_rep->obj;
543
544    *status = rpc_s_ok;
545}
546
547/*
548**++
549**
550**  ROUTINE NAME:       rpc_binding_reset
551**
552**  SCOPE:              PUBLIC - declared in rpc.idl
553**
554**  DESCRIPTION:
555**
556**  This routine will clear the endpoint in the RPC address of the Binding
557**  Rep. The Network Address Family Extension Service identified by the
558**  NAF ID in the RPC address will be called to actually clear the endpoint
559**  since its format is NAF-specific. Finally the RPC Protocol Service
560**  identifed by the RPC Protocol ID in the Binding Rep will be notified
561**  that the Binding Rep has changed.
562**
563**  INPUTS:
564**
565**      binding_h       The binding handle which points to the binding
566**                      rep data structure to be modified.
567**
568**  INPUTS/OUTPUTS:     none
569**
570**  OUTPUTS:
571**
572**      status          A value indicating the status of the routine.
573**
574**          rpc_s_ok        The call was successful.
575**          rpc_s_invalid_binding
576**                          RPC Protocol ID in binding handle was invalid.
577**          rpc_s_coding_error
578**
579**  IMPLICIT INPUTS:    none
580**
581**  IMPLICIT OUTPUTS:   none
582**
583**  FUNCTION VALUE:     void
584**
585**  SIDE EFFECTS:       none
586**
587**--
588**/
589
590PUBLIC void rpc_binding_reset
591(
592    rpc_binding_handle_t    binding_h,
593    unsigned32              *status
594)
595{
596    rpc_binding_rep_p_t     binding_rep = (rpc_binding_rep_p_t) binding_h;
597
598    assert(binding_rep != NULL);
599
600    CODING_ERROR (status);
601    RPC_VERIFY_INIT ();
602
603    RPC_BINDING_VALIDATE_CLIENT(binding_rep, status);
604    if (*status != rpc_s_ok)
605        return;
606
607    /*
608     * There is no longer a server instance associated with the binding.
609     */
610
611    RPC_LOCK(0);
612    binding_rep->bound_server_instance = false;
613    RPC_UNLOCK(0);
614
615    /*
616     * if binding endpoint is not set, don't do anything
617     */
618    if (!binding_rep->addr_has_endpoint)
619    {
620        *status = rpc_s_ok;
621        return;
622    }
623
624    assert(binding_rep->rpc_addr != NULL);
625
626    /*
627     * Tell the NAF extension service to clear the endpoint. A zero
628     * length string *must* be passed in to naf_addr_set_endpoint to
629     * clear the endpoint. Do *not* pass in NULL. This will generate a
630     * dynamic endpoint in certain nafs.
631     */
632    (*rpc_g_naf_id[binding_rep->rpc_addr->sa.family].epv
633        ->naf_addr_set_endpoint)
634            ((unsigned_char_p_t) "", &(binding_rep->rpc_addr), status);
635    if (*status != rpc_s_ok) return;
636
637    /*
638     * clear the endpoint flag in the binding rep
639     */
640    binding_rep->addr_has_endpoint = false;
641
642    /*
643     * notify the protocol service that the binding rep has been reset
644     */
645    (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
646        ->binding_reset) (binding_rep, status);
647}
648
649/*
650**++
651**
652**  ROUTINE NAME:       rpc_binding_copy
653**
654**  SCOPE:              PUBLIC - declared in rpc.idl
655**
656**  DESCRIPTION:
657**
658**  This routine will allocate a new Binding Rep through the RPC Protocol
659**  Service. The common part of the Binding Rep will then be filled in and
660**  the RPC Protocol Service will be called to initialize the RPC Protocol
661**  Service-specific part of the Binding Rep.
662**
663**  INPUTS:
664**
665**      src_binding_h   The binding handle which points to the source
666**                      binding rep data structure to be copied.
667**
668**  INPUTS/OUTPUTS:     none
669**
670**  OUTPUTS:
671**
672**      dst_binding_h   The binding handle which points to the destination
673**                      binding rep data structure to be created.
674**
675**      status          A value indicating the status of the routine.
676**
677**          rpc_s_ok        The call was successful.
678**          rpc_s_invalid_binding
679**                          RPC Protocol ID in binding handle was invalid.
680**          rpc_s_coding_error
681**
682**  IMPLICIT INPUTS:    none
683**
684**  IMPLICIT OUTPUTS:   none
685**
686**  FUNCTION VALUE:     void
687**
688**  SIDE EFFECTS:       none
689**
690**--
691**/
692
693PUBLIC void rpc_binding_copy
694(
695    rpc_binding_handle_t    src_binding_h,
696    rpc_binding_handle_t    *dst_binding_h,
697    unsigned32              *status
698)
699{
700    rpc_binding_rep_p_t     src_binding_rep = (rpc_binding_rep_p_t) src_binding_h;
701    rpc_binding_rep_p_t     dst_binding_rep;
702    rpc_addr_p_t            rpc_addr;
703    unsigned32              tmp_status;
704    boolean                 have_addr = false;
705    rpc_cs_method_eval_p_t  method_s_p;
706    rpc_cs_method_eval_p_t  method_d_p;
707    rpc_cs_tags_eval_p_t    tags_s_p;
708    rpc_cs_tags_eval_p_t    tags_d_p;
709
710    if (src_binding_rep == NULL)
711    {
712        *status = rpc_s_invalid_arg;
713        return;
714    }
715
716    CODING_ERROR (status);
717    RPC_VERIFY_INIT ();
718
719    RPC_BINDING_VALIDATE_CLIENT(src_binding_rep, status);
720    if (*status != rpc_s_ok)
721        return;
722
723    if (src_binding_rep->rpc_addr == NULL)
724    {
725        *status = rpc_s_invalid_arg;
726        return;
727    }
728
729    (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv
730        ->naf_addr_copy)
731            (src_binding_rep->rpc_addr, &rpc_addr, status);
732    if (*status != rpc_s_ok) return;
733
734    have_addr = true;
735
736    /*
737     * allocate a binding rep to hold the copy and init it from the source
738     */
739    dst_binding_rep = rpc__binding_alloc (
740        (boolean)src_binding_rep->is_server, &src_binding_rep->obj,
741        src_binding_rep->protocol_id, rpc_addr, status);
742    if (*status != rpc_s_ok) goto CLEANUP;
743
744    /*
745     * copy other common parts of the binding rep from the source to dest
746     */
747    dst_binding_rep->timeout            = src_binding_rep->timeout;
748    dst_binding_rep->call_timeout_time  = src_binding_rep->call_timeout_time;
749    dst_binding_rep->addr_is_dynamic    = src_binding_rep->addr_is_dynamic;
750    dst_binding_rep->bound_server_instance
751                                        = src_binding_rep->bound_server_instance;
752    dst_binding_rep->extended_bind_flag = src_binding_rep->extended_bind_flag;
753
754    /*
755     * Copy the auth info.
756     */
757    if (src_binding_rep->auth_info != NULL)
758    {
759        rpc__auth_info_reference (src_binding_rep->auth_info);
760        dst_binding_rep->auth_info = src_binding_rep->auth_info;
761    }
762
763    /*
764     * Copy transport information
765     */
766
767    if (src_binding_rep->transport_info != NULL)
768    {
769        rpc__transport_info_retain(src_binding_rep->transport_info);
770        dst_binding_rep->transport_info = src_binding_rep->transport_info;
771    }
772
773    /*
774     * Copy the protocol version
775     */
776    if (src_binding_rep->protocol_version != NULL)
777    {
778        rpc__binding_prot_version_alloc(
779                            &(dst_binding_rep->protocol_version),
780                            src_binding_rep->protocol_version->major_version,
781                            src_binding_rep->protocol_version->minor_version,
782                            status);
783        if (*status != rpc_s_ok) goto CLEANUP;
784    }
785
786    /*
787     * Copy the ns_specific.
788     */
789    if (src_binding_rep->ns_specific != NULL)
790    {
791        /* 		NOTE
792         *  This needs to be replaced with the real copy.
793         *  For now set the field to NULL so later we don't improperly
794         *  try to free the field.
795         *
796         *  When we get around to doing this, see how this field is
797         *  freed in rpc_binding_free for a hint on doing this.
798         *  You'll probably need to add a similar entry point in nsinit.c
799	 */
800        dst_binding_rep->ns_specific = NULL;
801    }
802
803    /*
804     * Copy the extended code set i14y information
805     */
806    if (src_binding_rep->extended_bind_flag == RPC_C_BH_EXTENDED_CODESETS)
807    {
808	/* Copy codesets relating binding information.
809	 * Determine the data structure
810	 */
811	switch (src_binding_rep->cs_eval.key)
812	{
813	case RPC_CS_EVAL_METHOD:
814		method_s_p = &src_binding_rep->cs_eval.tagged_union.method_key;
815		method_d_p = &dst_binding_rep->cs_eval.tagged_union.method_key;
816
817		dst_binding_rep->cs_eval.key = src_binding_rep->cs_eval.key;
818		method_d_p->method = method_s_p->method;
819		method_d_p->tags.stag = method_s_p->tags.stag;
820		method_d_p->tags.drtag = method_s_p->tags.drtag;
821		method_d_p->tags.stag_max_bytes
822					= method_s_p->tags.stag_max_bytes;
823		method_d_p->tags.client_tag = method_s_p->tags.client_tag;
824		method_d_p->tags.client_max_bytes
825					= method_s_p->tags.client_max_bytes;
826		method_d_p->tags.type_handle = method_d_p->tags.type_handle;
827		method_d_p->fixed = method_s_p->fixed;
828		method_d_p->cs_stub_eval_func = method_s_p->cs_stub_eval_func;
829
830		method_s_p->server = NULL;
831		method_d_p->client = NULL;
832
833		break;
834
835	case RPC_CS_EVAL_TAGS:
836		tags_s_p = &src_binding_rep->cs_eval.tagged_union.tags_key;
837		tags_d_p = &dst_binding_rep->cs_eval.tagged_union.tags_key;
838
839		dst_binding_rep->cs_eval.key = src_binding_rep->cs_eval.key;
840		tags_d_p->stag = tags_s_p->stag;
841		tags_d_p->drtag = tags_s_p->drtag;
842		tags_d_p->stag_max_bytes = tags_s_p->stag_max_bytes;
843		tags_d_p->client_tag = tags_s_p->client_tag;
844		tags_d_p->client_max_bytes = tags_s_p->client_max_bytes;
845		tags_d_p->type_handle = tags_d_p->type_handle;
846
847		break;
848
849	default:
850		*status = rpc_s_ss_invalid_codeset_tag;
851		break;
852	}
853    }
854
855    /*
856     * return the destination binding rep as a binding handle
857     */
858    *dst_binding_h = (rpc_binding_handle_t) dst_binding_rep;
859
860    /*
861     * let the protocol service copy any stuff it wants to
862     */
863    (*rpc_g_protocol_id[src_binding_rep->protocol_id].binding_epv
864        ->binding_copy) (src_binding_rep, dst_binding_rep, status);
865
866CLEANUP:
867
868    if (*status != rpc_s_ok && have_addr)
869        rpc__naf_addr_free (&rpc_addr, &tmp_status);
870}
871
872/*
873**++
874**
875**  ROUTINE NAME:       rpc_binding_to_string_binding
876**
877**  SCOPE:              PUBLIC - declared in rpc.idl
878**
879**  DESCRIPTION:
880**
881**  This routine will convert a Binding Rep data structure to its string
882**  represenation, which is called a "string binding". It will first convert
883**  the object UUID contained in the Binding Rep to string format. The string
884**  format of the Protocol Sequence ID contained in the RPC Address will be
885**  looked up in the RPC Protocol Sequence ID table. It will the call the
886**  appropriate Network Address Family Extension Service to return the
887**  endpoint, network address and network options form the RPC Address in the
888**  Binding Rep.
889**
890**  INPUTS:
891**
892**      binding_h       The binding handle which points to the binding
893**                      rep data structure to be converted.
894**
895**  INPUTS/OUTPUTS:     none
896**
897**  OUTPUTS:
898**
899**      string_binding  A string representation of the binding rep data
900**                      structure.
901**
902**      status          A value indicating the status of the routine.
903**
904**          rpc_s_ok        The call was successful.
905**          rpc_s_invalid_binding
906**                          RPC Protocol ID in binding handle was invalid.
907**          rpc_s_coding_error
908**
909**  IMPLICIT INPUTS:    none
910**
911**  IMPLICIT OUTPUTS:   none
912**
913**  FUNCTION VALUE:     void
914**
915**  SIDE EFFECTS:       none
916**
917**--
918**/
919
920PUBLIC void rpc_binding_to_string_binding
921(
922    rpc_binding_handle_t    binding_h,
923    unsigned_char_p_t       *string_binding,
924    unsigned32              *status
925)
926{
927    rpc_binding_rep_p_t     binding_rep = (rpc_binding_rep_p_t) binding_h;
928    rpc_addr_p_t            rpc_addr = NULL;
929    unsigned_char_p_t       object_uuid = NULL;
930    unsigned_char_p_t       endpoint = NULL;
931    unsigned_char_p_t       netaddr = NULL;
932    unsigned_char_p_t       network_options = NULL;
933    unsigned32              temp_status;
934
935    assert(binding_rep != NULL);
936
937    CODING_ERROR (status);
938    RPC_VERIFY_INIT ();
939
940    /*
941     * if the output argument is NULL, don't do anything
942     */
943    if (string_binding == NULL)
944    {
945        *status = rpc_s_ok;
946        return;
947    }
948
949    RPC_BINDING_VALIDATE(binding_rep, status);
950    if (*status != rpc_s_ok)
951        return;
952
953    /*
954     * convert the object UUID in the binding rep to string format
955     * (if it is non-nil - otherwise, keep it as a NULL pointer)
956     */
957    if (!uuid_is_nil (&(binding_rep->obj), status))
958    {
959        uuid_to_string (&(binding_rep->obj), &object_uuid, status);
960
961        if (*status != uuid_s_ok)
962        {
963            goto CLEANUP;
964        }
965    }
966
967    /*
968     * if the RPC address in the binding is NULL, get one from protocol service
969     */
970    if (binding_rep->rpc_addr == NULL)
971    {
972
973        /*
974         * get the RPC address from the protocol service
975         */
976        (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
977            ->binding_inq_addr) (binding_rep, &rpc_addr, status);
978
979        if (*status != rpc_s_ok)
980        {
981            goto CLEANUP;
982        }
983    }
984    else
985    {
986        /*
987         * otherwise use the RPC address in the binding rep
988         */
989        rpc_addr = binding_rep->rpc_addr;
990    }
991
992    /*
993     * get the endpoint from the network address family extension
994     */
995    (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_endpoint)
996        (rpc_addr, &endpoint, status);
997
998    if (*status != rpc_s_ok)
999    {
1000        goto CLEANUP;
1001    }
1002
1003    /*
1004     * get the network address from the network address family extension
1005     */
1006    (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_netaddr)
1007        (rpc_addr, &netaddr, status);
1008
1009    if (*status != rpc_s_ok)
1010    {
1011        goto CLEANUP;
1012    }
1013
1014    /*
1015     * get the network options from the network address family extension
1016     */
1017    (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_options)
1018        (rpc_addr, &network_options, status);
1019
1020    if (*status != rpc_s_ok)
1021    {
1022        goto CLEANUP;
1023    }
1024
1025    /*
1026     * got everything - now build the whole string
1027     * (note: if the object uuid was nil, a NULL will be passed here,
1028     * and it won't appear in the string binding; also note, we'll
1029     * return at this point with the status of rpc_string_binding_compose)
1030     */
1031    rpc_string_binding_compose (
1032        object_uuid, rpc_g_protseq_id[rpc_addr->rpc_protseq_id].rpc_protseq,
1033        netaddr, endpoint, network_options, string_binding, status);
1034
1035CLEANUP:
1036
1037    /*
1038     * if anything failed along the way, or we got here succesfully,
1039     * cleanup local buffers and return with the last meaningful status
1040     */
1041    if (object_uuid != NULL)
1042    {
1043        rpc_string_free (&object_uuid, &temp_status);
1044    }
1045
1046    if (endpoint != NULL)
1047    {
1048        rpc_string_free (&endpoint, &temp_status);
1049    }
1050
1051    if (netaddr != NULL)
1052    {
1053        rpc_string_free (&netaddr, &temp_status);
1054    }
1055
1056    if (network_options != NULL)
1057    {
1058        rpc_string_free (&network_options, &temp_status);
1059    }
1060}
1061
1062/*
1063**++
1064**
1065**  ROUTINE NAME:       rpc_binding_from_string_binding
1066**
1067**  SCOPE:              PUBLIC - declared in rpc.idl
1068**
1069**  DESCRIPTION:
1070**
1071**  This routine converts a string binding to a Binding Rep data structure.
1072**  It will strip the object UUID, RPC Protocol Sequence string, endpoint,
1073**  network address and network options out of the string binding provided.
1074**  A Binding Rep will then be allocated through the RPC Protocol Service
1075**  identified in the RPC Protocol Sequence. An RPC Address will be allocated
1076**  through the Network Address Family Extension Service identified in the
1077**  RPC Protocol Sequence. The common fields of the Binding Rep will be set
1078**  to defaults and the RPC Prtotcol Service will be called to initialize
1079**  the RPC Protocol Service-specific part of the Binding Rep.
1080**
1081**
1082**  If the string binding contains an endpoint, the addr_is_dynamic field
1083**  in the binding rep is set to false, indicating a well-known endpoint.
1084**  (This field is initialized to true in rpc__binding_alloc.)
1085**
1086**  INPUTS:
1087**
1088**      string_binding  A string representation of the binding rep data
1089**                      structure.
1090**
1091**  INPUTS/OUTPUTS:     none
1092**
1093**  OUTPUTS:
1094**
1095**      binding_h       The binding handle which points to the binding
1096**                      rep data structure to be created.
1097**
1098**      status          A value indicating the status of the routine.
1099**
1100**          rpc_s_ok        The call was successful.
1101**          uuid_s_invalid_string_uuid
1102**                          Object UUID in string binding was invalid.
1103**          rpc_s_invalid_string_binding
1104**                          String binding was invalid.
1105**          rpc_s_coding_error
1106**
1107**  IMPLICIT INPUTS:    none
1108**
1109**  IMPLICIT OUTPUTS:   none
1110**
1111**  FUNCTION VALUE:     void
1112**
1113**  SIDE EFFECTS:       none
1114**
1115**--
1116**/
1117
1118PUBLIC void rpc_binding_from_string_binding
1119(
1120    unsigned_char_p_t       string_binding,
1121    rpc_binding_handle_t    *binding_h,
1122    unsigned32              *status
1123)
1124{
1125    rpc_binding_rep_p_t     binding_rep;
1126    idl_uuid_t                  obj_uuid;
1127    rpc_addr_p_t            rpc_addr = NULL;
1128    unsigned_char_p_t       string_object_uuid = NULL;
1129    unsigned_char_p_t       protseq = NULL;
1130    unsigned_char_p_t       endpoint = NULL;
1131    unsigned_char_p_t       netaddr = NULL;
1132    unsigned_char_p_t       network_options = NULL;
1133    rpc_protseq_id_t        protseq_id;
1134    rpc_protocol_id_t       protocol_id;
1135    rpc_naf_id_t            naf_id = 0;
1136    unsigned32              temp_status;
1137
1138    CODING_ERROR (status);
1139    RPC_VERIFY_INIT ();
1140
1141    /*
1142     * extract the various fields from the string binding
1143     */
1144    rpc_string_binding_parse (string_binding, &string_object_uuid,
1145        &protseq, &netaddr, &endpoint, &network_options, status);
1146
1147    if (*status != rpc_s_ok)
1148    {
1149        goto CLEANUP;
1150    }
1151
1152    /*
1153     * Convert the protocol sequence string to and protseq ID.
1154     */
1155    protseq_id = rpc__network_pseq_id_from_pseq (protseq, status);
1156
1157    if (*status != rpc_s_ok)
1158    {
1159        goto CLEANUP;
1160    }
1161
1162    if (rpc_g_protseq_id[protseq_id].supported == false)
1163    {
1164        *status = rpc_s_protseq_not_supported;
1165        goto CLEANUP;
1166    }
1167
1168    protocol_id = rpc_g_protseq_id[protseq_id].rpc_protocol_id;
1169    naf_id      = rpc_g_protseq_id[protseq_id].naf_id;
1170
1171    /*
1172     * set the object UUID to the one given in the string
1173     * - if the string is empty, none was given - use the nil uuid
1174     */
1175    if (*string_object_uuid != '\0')
1176    {
1177        uuid_from_string (string_object_uuid, &obj_uuid, status);
1178    }
1179    else
1180    {
1181        uuid_create_nil (&obj_uuid, status);
1182    }
1183
1184    if (*status != uuid_s_ok)
1185    {
1186        goto CLEANUP;
1187    }
1188
1189    /*
1190     * A NULL network address means to bind to the local host.
1191     * Otherwise, get an RPC address from the Network Address Family
1192     * Extension Service.
1193     */
1194    if (*netaddr == '\0')
1195    {
1196        rpc__network_inq_local_addr (protseq_id, endpoint, &rpc_addr, status);
1197    }
1198    else
1199    {
1200        (*rpc_g_naf_id[naf_id].epv->naf_addr_alloc)
1201            (protseq_id, naf_id, endpoint, netaddr, network_options,
1202                &rpc_addr, status);
1203    }
1204
1205    if (*status != rpc_s_ok)
1206    {
1207        rpc_addr = NULL;
1208        goto CLEANUP;
1209    }
1210
1211    /*
1212     * allocate a binding rep and initialize it
1213     */
1214    binding_rep = rpc__binding_alloc
1215        ((boolean)false, &obj_uuid, protocol_id, rpc_addr, status);
1216
1217    if (*status != rpc_s_ok) goto CLEANUP;
1218
1219    /*
1220     * A non-NULL endpoint means that the endpoint is well-known, so set
1221     * the addr_is_dynamic field to false.
1222     */
1223    if (*endpoint != '\0')
1224    {
1225        binding_rep->addr_is_dynamic = false;
1226    }
1227
1228    /*
1229     * cast the binding handle to a binding rep pointer
1230     */
1231    *binding_h = (rpc_binding_handle_t) binding_rep;
1232
1233    *status = rpc_s_ok;
1234
1235CLEANUP:
1236
1237    if (string_object_uuid != NULL)
1238    {
1239        rpc_string_free (&string_object_uuid, &temp_status);
1240    }
1241
1242    if (protseq != NULL)
1243    {
1244        rpc_string_free (&protseq, &temp_status);
1245    }
1246
1247    if (endpoint != NULL)
1248    {
1249        rpc_string_free (&endpoint, &temp_status);
1250    }
1251
1252    if (netaddr != NULL)
1253    {
1254        rpc_string_free (&netaddr, &temp_status);
1255    }
1256
1257    if (network_options != NULL)
1258    {
1259        rpc_string_free (&network_options, &temp_status);
1260    }
1261
1262    if (*status != rpc_s_ok)
1263    {
1264        unsigned32     tstatus;
1265
1266        if (rpc_addr != NULL)
1267        {
1268            (*rpc_g_naf_id[naf_id].epv->naf_addr_free) (&rpc_addr, &tstatus);
1269        }
1270
1271        if (*status == rpc_s_invalid_binding)
1272        {
1273            *status = rpc_s_invalid_string_binding;
1274        }
1275
1276        *binding_h = NULL;
1277    }
1278}
1279
1280
1281PRIVATE void rpc__string_netaddr_escape
1282(
1283    unsigned_char_p_t   netaddr,
1284    unsigned_char_p_t   *escaped_netaddr,
1285    unsigned32          *status
1286)
1287{
1288    unsigned_char_p_t   saved_netaddr;
1289    unsigned_char_p_t   escaped_netaddr_ptr;
1290    size_t              escaped_string_size = 1; /* include null at end */
1291
1292    CODING_ERROR (status);
1293
1294    /*
1295     * if the output argument is NULL, don't do anything
1296     */
1297    if (escaped_netaddr == NULL)
1298    {
1299        *status = rpc_s_ok;
1300        return;
1301    }
1302
1303    /*
1304     * if the input argument is NULL, return NULL
1305     */
1306    if (netaddr == NULL)
1307    {
1308        *escaped_netaddr = NULL;
1309        *status = rpc_s_ok;
1310        return;
1311    }
1312
1313    /*
1314     * calculate total size of the string including escaped out chars
1315     */
1316    saved_netaddr = netaddr;
1317    while (*netaddr != '\0')
1318    {
1319        switch (*netaddr)
1320        {
1321            case ' ':
1322            case '@':
1323            case ':':
1324            case '[':
1325            case ']':
1326            case ',':
1327            case '\\':
1328                /* have to add one more char due to adding '\' */
1329                escaped_string_size += 2;
1330                break;
1331
1332            default:
1333                escaped_string_size += 1;
1334                break;
1335        }
1336        netaddr++;
1337    }
1338
1339    /*
1340     * heap allocate storage for the escaped string
1341     */
1342    RPC_MEM_ALLOC (*escaped_netaddr,
1343                   unsigned_char_p_t,
1344                   escaped_string_size,
1345                   RPC_C_MEM_STRING,
1346                   RPC_C_MEM_WAITOK);
1347
1348    escaped_netaddr_ptr = *escaped_netaddr;
1349
1350    /* make sure string ends in null */
1351    memset(escaped_netaddr_ptr, 0, escaped_string_size);
1352
1353    /*
1354     * copy chars and escape as needed
1355     */
1356    netaddr = saved_netaddr;
1357    while (*netaddr != '\0')
1358    {
1359        switch (*netaddr)
1360        {
1361            case ' ':
1362            case '@':
1363            case ':':
1364            case '[':
1365            case ']':
1366            case ',':
1367            case '\\':
1368                /* add escape char of '\' followed by the char */
1369                *(escaped_netaddr_ptr++) = '\\';
1370                *(escaped_netaddr_ptr++) = *(netaddr++);
1371                break;
1372
1373            default:
1374                /* no need to escape, just copy the char */
1375                *(escaped_netaddr_ptr++) = *(netaddr++);
1376                break;
1377        }
1378    }
1379
1380    *status = rpc_s_ok;
1381    return;
1382}
1383
1384
1385PRIVATE void rpc__string_netaddr_unescape
1386(
1387 unsigned_char_p_t   escaped_netaddr,
1388 unsigned_char_p_t   *netaddr,
1389 unsigned32          *status
1390)
1391{
1392    unsigned_char_p_t   netaddr_ptr;
1393    size_t              escaped_string_size;
1394    unsigned_char_p_t   p1, p2;
1395
1396    CODING_ERROR (status);
1397
1398    /*
1399     * if the output argument is NULL, don't do anything
1400     */
1401    if (netaddr == NULL)
1402    {
1403        *status = rpc_s_ok;
1404        return;
1405    }
1406
1407    /*
1408     * if the input argument is NULL, return NULL
1409     */
1410    if (escaped_netaddr == NULL)
1411    {
1412        *netaddr = NULL;
1413        *status = rpc_s_ok;
1414        return;
1415    }
1416
1417    /*
1418     * The unescaped string will be the same length or shorter than
1419     * the escaped string so allocate same size as the escaped string.
1420     */
1421    escaped_string_size = strlen ((char*) escaped_netaddr);
1422
1423    /*
1424     * heap allocate storage for the unescaped string
1425     */
1426    RPC_MEM_ALLOC (*netaddr,
1427                   unsigned_char_p_t,
1428                   escaped_string_size + 1,
1429                   RPC_C_MEM_STRING,
1430                   RPC_C_MEM_WAITOK);
1431
1432    netaddr_ptr = *netaddr;
1433
1434    /* make sure string ends in null */
1435    memset(netaddr_ptr, 0, escaped_string_size + 1);
1436
1437    /*
1438     * copy the string, filtering out escape chars
1439     */
1440    p2 = netaddr_ptr;
1441    p1 = escaped_netaddr;
1442
1443    while (*p1 != '\0')
1444    {
1445        switch (*p1)
1446        {
1447            case '\\':
1448                /* skip escape char of '\' and just copy the char */
1449                if (p1[1] != '\0') {
1450                    p1++;
1451                    *(p2++) = *(p1++);
1452                }
1453                else {
1454                    /* must be at end of escaped string so just copy the '\' */
1455                    *(p2++) = *(p1++);
1456                }
1457                break;
1458
1459            default:
1460                /* no need to unescape, just copy the char */
1461                *(p2++) = *(p1++);
1462                break;
1463        }
1464    }
1465
1466    *status = rpc_s_ok;
1467    return;
1468}
1469
1470
1471/*
1472**++
1473**
1474**  ROUTINE NAME:       rpc_string_binding_parse
1475**
1476**  SCOPE:              PUBLIC - declared in rpc.idl
1477**
1478**  DESCRIPTION:
1479**
1480**  This routine will split the string binding provided into multiple
1481**  components.
1482**
1483**  INPUTS:
1484**
1485**      string_binding  A string representation of the binding rep data
1486**                      structure.
1487**
1488**  INPUTS/OUTPUTS:     none
1489**
1490**  OUTPUTS:
1491**
1492**      string_obj_uuid A string representation of an object UUID.
1493**
1494**      protseq         An RPC Protocol Sequence.
1495**
1496**      netaddr         A Network Address.
1497**
1498**      endpoint        An RPC Endpoint.
1499**
1500**      network_options A string of Network Options.
1501**
1502**      status          A value indicating the status of the routine.
1503**
1504**          rpc_s_ok        The call was successful.
1505**          rpc_s_invalid_string_binding
1506**                          The string binding could not be parsed
1507**          rpc_s_coding_error
1508**
1509**  IMPLICIT INPUTS:    none
1510**
1511**  IMPLICIT OUTPUTS:   none
1512**
1513**  FUNCTION VALUE:     void
1514**
1515**  SIDE EFFECTS:       none
1516**
1517**--
1518**/
1519
1520PUBLIC void rpc_string_binding_parse
1521(
1522    unsigned_char_p_t       string_binding,
1523    unsigned_char_p_t       *string_object_uuid,
1524    unsigned_char_p_t       *protseq,
1525    unsigned_char_p_t       *netaddr,
1526    unsigned_char_p_t       *endpoint,
1527    unsigned_char_p_t       *network_options,
1528    unsigned32              *status
1529)
1530{
1531#define RPC_C_NETWORK_OPTIONS_MAX   1024
1532
1533    unsigned_char_p_t       binding_ptr;
1534    unsigned_char_p_t       option_ptr = NULL;
1535    size_t                  count;
1536    boolean                 get_endpoint;
1537    unsigned32              temp_status;
1538    size_t                  len;
1539    unsigned_char_p_t       escaped_netaddr;
1540
1541    CODING_ERROR (status);
1542    RPC_VERIFY_INIT ();
1543
1544    /*
1545     * make sure we have something to start with
1546     */
1547    if (string_binding == NULL)
1548    {
1549        *status = rpc_s_invalid_string_binding;
1550        return;
1551    }
1552
1553    /*
1554     * Initialize netaddr, endpoint and network_options if pointers are non-NULL
1555     */
1556    if (netaddr != NULL)
1557    {
1558        *netaddr = NULL;
1559    }
1560    if (endpoint != NULL)
1561    {
1562        *endpoint = NULL;
1563    }
1564    if (network_options != NULL)
1565    {
1566        *network_options = NULL;
1567    }
1568
1569    binding_ptr = string_binding;
1570
1571    /*
1572     * get in the object UUID and protocol sequence
1573     */
1574    count = rpc__strcspn (binding_ptr, "@");
1575    if (string_object_uuid != NULL)
1576    {
1577        {
1578            RPC_MEM_ALLOC (
1579                *string_object_uuid,
1580                unsigned_char_p_t,
1581                count + 1,
1582                RPC_C_MEM_STRING,
1583                RPC_C_MEM_WAITOK);
1584
1585            if (count > 0)
1586            {
1587                rpc__strncpy (*string_object_uuid, binding_ptr, count - 1);
1588            }
1589            else
1590            {
1591                **string_object_uuid = '\0';
1592            }
1593        }
1594    }
1595    /*
1596     * In any case, advance the pointer.
1597     */
1598    binding_ptr += count;
1599
1600    count = rpc__strcspn (binding_ptr, ":");
1601    if (protseq != NULL)
1602    {
1603        {
1604            RPC_MEM_ALLOC (
1605                *protseq,
1606                unsigned_char_p_t,
1607                count + 1,
1608                RPC_C_MEM_STRING,
1609                RPC_C_MEM_WAITOK);
1610
1611            if (count > 0)
1612            {
1613                rpc__strncpy (*protseq, binding_ptr, count - 1);
1614            }
1615            else
1616            {
1617                **protseq = '\0';
1618            }
1619        }
1620    }
1621    /*
1622     * In any case, advance the pointer.
1623     */
1624    binding_ptr += count;
1625
1626    /*
1627     * see if there are options after the network address
1628     */
1629    if ((count = rpc__strcspn (binding_ptr, "[")) == 0)
1630    {
1631        /*
1632         * if there was no '[' terminator, maybe there are no options -
1633         * but there still might be a network address - go for it!
1634         */
1635        if (netaddr != NULL)
1636        {
1637            len = strlen ((char *) binding_ptr);
1638            RPC_MEM_ALLOC (
1639                *netaddr,
1640                unsigned_char_p_t,
1641                len + 1,
1642                RPC_C_MEM_STRING,
1643                RPC_C_MEM_WAITOK);
1644
1645            /*
1646             * Note: we are counting on null termination here, even if len == 0
1647             */
1648            rpc__strncpy (*netaddr, binding_ptr, len);
1649        }
1650    }
1651    else
1652    {
1653        /*
1654         * if there are options, first get the network address
1655         */
1656        if (netaddr != NULL)
1657        {
1658            RPC_MEM_ALLOC (
1659                *netaddr,
1660                unsigned_char_p_t,
1661                count,
1662                RPC_C_MEM_STRING,
1663                RPC_C_MEM_WAITOK);
1664
1665            rpc__strncpy (*netaddr, binding_ptr, count - 1);
1666        }
1667        binding_ptr += count;
1668
1669        /*
1670         * then get the entries in the options list one by one
1671         */
1672        if (network_options != NULL)
1673        {
1674            /*
1675             * we've got to allocate enough space to catch all of the
1676             * network options that might conceivably be here - a lot
1677             * will probably be wasted, but we have no way of knowing at
1678             * this time exactly how much, but we know it can be no more than
1679             * the length of what remains of this string binding.
1680             */
1681
1682              /*
1683               * Allocate one byte more than we need to cover bug -
1684               * see modification history for 21-may-91.
1685               */
1686            RPC_MEM_ALLOC (
1687                *network_options,
1688                unsigned_char_p_t,
1689                strlen ((char *)binding_ptr) + 1,
1690                RPC_C_MEM_STRING,
1691                RPC_C_MEM_WAITOK);
1692
1693            option_ptr = *network_options;
1694            *option_ptr = '\0';
1695        }
1696
1697        while ((count > 0) && (*binding_ptr != '\0'))
1698        {
1699            get_endpoint = false;
1700
1701            /*
1702             * first see if there's an option tag
1703             */
1704            count = rpc__strcspn (binding_ptr, "=,");
1705
1706            if (count == 0 || *(binding_ptr + count - 1) != '=')
1707            {
1708                /*
1709                 * if there's no option tag, this must be an endpoint
1710                 */
1711                get_endpoint = true;
1712            }
1713            else
1714            {
1715                /*
1716                 * see if the tag is an endpoint specifier -
1717                 * but skip over any leading white space
1718                 */
1719                for (; (*binding_ptr == ' ' || *binding_ptr == '\t') &&
1720                    *binding_ptr != '\0'; binding_ptr++, count--);
1721
1722                if ((strncmp ((char *) binding_ptr, "endpoint", (count-1)))
1723                    == 0)
1724                {
1725                    /*
1726                     * if the tag was "endpoint", skip to the equal sign
1727                     */
1728                    get_endpoint = true;
1729                    binding_ptr += count;
1730                }
1731            }
1732
1733            /*
1734             * if this is an endpoint, collect it
1735             */
1736            if (get_endpoint && endpoint != NULL)
1737            {
1738                size_t token_end;
1739                /*
1740                 * We want to return an error if there is more than one
1741                 * endpoint specified (this will also catch an endpoint
1742                 * specified with extra brackets, like "[[foo]]" as a side
1743                 * effect).
1744                 */
1745                if (*endpoint != NULL)
1746                {
1747                    *status = rpc_s_invalid_string_binding;
1748                    goto CLEANUP;
1749                }
1750
1751                token_end = rpc__get_token(binding_ptr, '\\', ",]",
1752                        endpoint, status);
1753
1754                if(*status != rpc_s_ok)
1755                    goto CLEANUP;
1756
1757                /*
1758                 * We want to return an error if there is no closing ']';
1759                 */
1760                if (binding_ptr[token_end] == '\0')
1761                {
1762                    *status = rpc_s_invalid_string_binding;
1763                    goto CLEANUP;
1764                }
1765
1766                binding_ptr += token_end + 1;
1767            }
1768            else if (get_endpoint && endpoint == NULL)
1769            /*
1770             * Skip over the endpoint
1771             */
1772            {
1773                size_t token_end = rpc__get_token(binding_ptr, '\\', ",]",
1774                        NULL, status);
1775                binding_ptr += token_end + 1;
1776            }
1777            else
1778            {
1779                count = rpc__strcspn (binding_ptr, ",]");
1780                /*
1781                 * If this is the last token, make sure the string is properly terminated.
1782                 */
1783                if ((count == 0) && ((strlen ((char *) binding_ptr)) != 0))
1784                {
1785                    *status = rpc_s_invalid_string_binding;
1786                    goto CLEANUP;
1787                }
1788
1789                /*
1790                 * if not an endpoint, collect the option tag and value
1791                 */
1792                if (network_options != NULL)
1793                {
1794                    /*
1795                     * We can have any number of network options, but we'll
1796                     * lose the last one if the string doesn't have a
1797                     * terminator.
1798                     * (this code is probably redundant, now)
1799                     */
1800                    if (count == 0)
1801                    {
1802                        *status = rpc_s_invalid_string_binding;
1803                        goto CLEANUP;
1804                    }
1805
1806                    rpc__strncpy (option_ptr, binding_ptr, count);
1807                    option_ptr += count;
1808                }
1809
1810                /*
1811                 * advance to the next token in the string.
1812                 */
1813                binding_ptr += count;
1814            }
1815        }
1816    }
1817
1818    /*
1819     * if component strings were created, compress white space out of the
1820     * results - otherwise, return empty strings for things that were wanted
1821     * but not found
1822     */
1823    if (string_object_uuid != NULL)
1824    {
1825        if (*string_object_uuid != NULL)
1826        {
1827            rpc__strsqz (*string_object_uuid);
1828        }
1829        else
1830        {
1831            RPC_MEM_ALLOC (
1832                *string_object_uuid,
1833                unsigned_char_p_t,
1834                1,
1835                RPC_C_MEM_STRING,
1836                RPC_C_MEM_WAITOK);
1837
1838            **string_object_uuid = '\0';
1839        }
1840    }
1841
1842    if (protseq != NULL)
1843    {
1844        if (*protseq != NULL)
1845        {
1846            rpc__strsqz (*protseq);
1847        }
1848        else
1849        {
1850            RPC_MEM_ALLOC (
1851                *protseq,
1852                unsigned_char_p_t,
1853                1,
1854                RPC_C_MEM_STRING,
1855                RPC_C_MEM_WAITOK);
1856
1857            **protseq = '\0';
1858        }
1859    }
1860
1861    if (netaddr != NULL)
1862    {
1863        if (*netaddr != NULL)
1864        {
1865            /*
1866             * call rpc__strsqz before unescaping so that dont lose any escaped
1867             * spaces
1868             */
1869            rpc__strsqz (*netaddr);
1870
1871            /* unescape the netaddr before returning it */
1872            escaped_netaddr = *netaddr;
1873            rpc__string_netaddr_unescape(escaped_netaddr, netaddr, &temp_status);
1874            if (temp_status == rpc_s_ok)
1875            {
1876                /* free the escaped netaddr */
1877                rpc_string_free (&escaped_netaddr, &temp_status);
1878            }
1879            else
1880            {
1881                /* error occurred so restore original netaddr */
1882                *netaddr = escaped_netaddr;
1883            }
1884        }
1885        else
1886        {
1887            RPC_MEM_ALLOC (
1888                *netaddr,
1889                unsigned_char_p_t,
1890                1,
1891                RPC_C_MEM_STRING,
1892                RPC_C_MEM_WAITOK);
1893
1894            **netaddr = '\0';
1895        }
1896    }
1897
1898    if (endpoint != NULL)
1899    {
1900        if (*endpoint != NULL)
1901        {
1902            rpc__strsqz (*endpoint);
1903        }
1904        else
1905        {
1906            RPC_MEM_ALLOC (
1907                *endpoint,
1908                unsigned_char_p_t,
1909                1,
1910                RPC_C_MEM_STRING,
1911                RPC_C_MEM_WAITOK);
1912
1913            **endpoint = '\0';
1914        }
1915    }
1916
1917    if (network_options != NULL)
1918    {
1919        if (*network_options != NULL)
1920        {
1921            rpc__strsqz (*network_options);
1922
1923            /*
1924             * clip the trailing separator off the network options string
1925             * to be neat
1926             */
1927            if ((count = strlen ((char *) *network_options)) > 0)
1928            {
1929                (*network_options)[count - 1] = '\0';
1930            }
1931        }
1932        else
1933        {
1934            RPC_MEM_ALLOC (
1935                *network_options,
1936                unsigned_char_p_t,
1937                1,
1938                RPC_C_MEM_STRING,
1939                RPC_C_MEM_WAITOK);
1940
1941            **network_options = '\0';
1942        }
1943    }
1944
1945    *status = rpc_s_ok;
1946    return;
1947
1948CLEANUP:
1949
1950    /*
1951     * free any buffers that have been allocated
1952     */
1953    if (string_object_uuid != NULL && *string_object_uuid != NULL)
1954    {
1955        rpc_string_free (string_object_uuid, &temp_status);
1956    }
1957
1958    if (protseq != NULL && *protseq != NULL)
1959    {
1960        rpc_string_free (protseq, &temp_status);
1961    }
1962
1963    if (netaddr != NULL && *netaddr != NULL)
1964    {
1965        rpc_string_free (netaddr, &temp_status);
1966    }
1967
1968    if (endpoint != NULL && *endpoint != NULL)
1969    {
1970        rpc_string_free (endpoint, &temp_status);
1971    }
1972
1973    if (network_options != NULL && *network_options != NULL)
1974    {
1975        rpc_string_free (network_options, &temp_status);
1976    }
1977
1978    return;
1979}
1980
1981/*
1982**++
1983**
1984**  ROUTINE NAME:       rpc_string_binding_compose
1985**
1986**  SCOPE:              PUBLIC - declared in rpc.idl
1987**
1988**  DESCRIPTION:
1989**
1990**  This routine will combine the components of a string binding and
1991**  return a formatted string binding.
1992**
1993**  INPUTS:
1994**
1995**      string_obj_uuid A string representation of an object UUID.
1996**
1997**      protseq         An RPC Protocol Sequence.
1998**
1999**      netaddr         A Network Address.
2000**
2001**      endpoint        An RPC Endpoint.
2002**
2003**      network_options A string of Network Options.
2004**
2005**  INPUTS/OUTPUTS:     none
2006**
2007**  OUTPUTS:
2008**
2009**      string_binding  A string representation of the binding rep data
2010**                      structure.
2011**
2012**      status          A value indicating the status of the routine.
2013**
2014**          rpc_s_ok        The call was successful.
2015**          rpc_s_invalid_binding
2016**                          RPC Protocol ID in binding handle was invalid.
2017**          rpc_s_coding_error
2018**
2019**  IMPLICIT INPUTS:    none
2020**
2021**  IMPLICIT OUTPUTS:   none
2022**
2023**  FUNCTION VALUE:     void
2024**
2025**  SIDE EFFECTS:       none
2026**
2027**--
2028**/
2029
2030PUBLIC void rpc_string_binding_compose
2031(
2032    unsigned_char_p_t       string_object_uuid,
2033    unsigned_char_p_t       protseq,
2034    unsigned_char_p_t       netaddr,
2035    unsigned_char_p_t       endpoint,
2036    unsigned_char_p_t       network_options,
2037    unsigned_char_p_t       *string_binding,
2038    unsigned32              *status
2039)
2040{
2041    unsigned_char_p_t   string_binding_ptr;
2042    unsigned32          string_binding_size = 1;
2043    unsigned_char_p_t   escaped_netaddr = NULL;
2044    unsigned_char_p_t   temp_netaddr = NULL;
2045
2046    CODING_ERROR (status);
2047    RPC_VERIFY_INIT ();
2048
2049    /*
2050     * if the output argument is NULL, don't do anything
2051     */
2052    if (string_binding == NULL)
2053    {
2054        *status = rpc_s_ok;
2055        return;
2056    }
2057
2058    /*
2059     * calculate the total size of the resulting string binding - the sum
2060     * of the lengths of all the non-null input strings, plus space for
2061     * any delimiters that might possibly be needed (and the requisite
2062     * null terminator)
2063     */
2064    if ((string_object_uuid != NULL) && (*string_object_uuid != '\0'))
2065    {
2066        string_binding_size += strlen ((char *) string_object_uuid) + 1;
2067    }
2068
2069    if (protseq != NULL)
2070    {
2071        string_binding_size += strlen ((char *) protseq) + 1;
2072    }
2073
2074    if (netaddr != NULL)
2075    {
2076        /* escape out the netaddr string */
2077        rpc__string_netaddr_escape(netaddr, &escaped_netaddr, status);
2078        if (*status == rpc_s_ok)
2079        {
2080            /* add in the len of the escaped string */
2081            string_binding_size += strlen ((char *) escaped_netaddr) + 1;
2082        }
2083        else
2084        {
2085            /* error occurred so add in the len of netaddr */
2086            string_binding_size += strlen ((char *) netaddr) + 1;
2087        }
2088
2089    }
2090
2091    if (endpoint != NULL)
2092    {
2093        string_binding_size += strlen ((char *) endpoint) + 2;
2094    }
2095
2096    if (network_options != NULL)
2097    {
2098        string_binding_size += strlen ((char *) network_options) + 2;
2099    }
2100
2101    /*
2102     * heap allocate storage for the string binding
2103     */
2104    RPC_MEM_ALLOC (
2105        *string_binding,
2106        unsigned_char_p_t,
2107        string_binding_size,
2108        RPC_C_MEM_STRING,
2109        RPC_C_MEM_WAITOK);
2110
2111    string_binding_ptr = *string_binding;
2112
2113    /*
2114     * fill in the object UUID
2115     */
2116    if ((string_object_uuid != NULL) && (*string_object_uuid != '\0'))
2117    {
2118        while (*string_object_uuid != '\0')
2119        {
2120            *(string_binding_ptr++) = *(string_object_uuid++);
2121        }
2122
2123        *(string_binding_ptr++) = '@';
2124    }
2125
2126    /*
2127     * fill in the protocol sequence
2128     */
2129    if (protseq != NULL)
2130    {
2131        while (*protseq != '\0')
2132        {
2133            *(string_binding_ptr++) = *(protseq++);
2134        }
2135
2136        *(string_binding_ptr++) = ':';
2137    }
2138
2139    /*
2140     * fill in the network address
2141     */
2142    if (escaped_netaddr != NULL)
2143    {
2144        temp_netaddr = escaped_netaddr;
2145        while (*temp_netaddr != '\0')
2146        {
2147            *(string_binding_ptr++) = *(temp_netaddr++);
2148        }
2149        rpc_string_free (&escaped_netaddr, status);
2150    }
2151    else
2152    {
2153        /*
2154         * maybe an error occurred when trying to escape the netaddr?
2155         * try to copy in the original netaddr
2156         */
2157        if (netaddr != NULL)
2158        {
2159            while (*netaddr != '\0')
2160            {
2161                *(string_binding_ptr++) = *(netaddr++);
2162            }
2163        }
2164    }
2165
2166    if (endpoint != NULL || network_options != NULL)
2167    {
2168        *(string_binding_ptr++) = '[';
2169
2170        /*
2171         * fill in the endpoint
2172         */
2173        if (endpoint != NULL)
2174        {
2175            while (*endpoint != '\0')
2176            {
2177                *(string_binding_ptr++) = *(endpoint++);
2178            }
2179
2180            if (network_options != NULL && *network_options != '\0')
2181            {
2182                 *(string_binding_ptr++) = ',';
2183            }
2184        }
2185
2186        /*
2187         * fill in any other options that might be specified
2188         */
2189        if (network_options != NULL)
2190        {
2191            while (*network_options != '\0')
2192            {
2193                *(string_binding_ptr++) = *(network_options++);
2194            }
2195        }
2196
2197        *(string_binding_ptr++) = ']';
2198    }
2199
2200    /*
2201     * terminate the string
2202     */
2203    *(string_binding_ptr) = '\0';
2204
2205    *status = rpc_s_ok;
2206    return;
2207}
2208
2209/*
2210**++
2211**
2212**  ROUTINE NAME:       rpc__binding_alloc
2213**
2214**  SCOPE:              PRIVATE - declared in combind.h
2215**
2216**  DESCRIPTION:
2217**
2218**  This routine will allocate the memory for a Binding Rep data structure
2219**  through the RPC Protocol Service identified in the input arguments.
2220**  All the common fields of the Binding Rep will be initialized using
2221**  defaults and the input arguments to this routine. The RPC Protocol
2222**  Service will then be called to initialize the RPC Protocol Service
2223**  specific parts of the Binding Rep.
2224**
2225**  INPUTS:
2226**
2227**      is_server       T => a server-side binding handle should be created
2228**
2229**      object_uuid     The unique identifier of an object to which an
2230**                      RPC may be made.
2231**
2232**      protocol_id     The identifier of an RPC Protocol Service through
2233**                      which an RPC may be made. Since this is an internal
2234**                      routine it assumes this has been checked by the
2235**                      caller to see if it is a valid identifier.
2236**
2237**      rpc_addr        The location of the remote half of the RPC.
2238**
2239**  INPUTS/OUTPUTS:     none
2240**
2241**  OUTPUTS:
2242**
2243**      status          A value indicating the status of the routine.
2244**
2245**          rpc_s_ok        The call was successful.
2246**          rpc_s_coding_error
2247**
2248**  IMPLICIT INPUTS:    none
2249**
2250**  IMPLICIT OUTPUTS:   none
2251**
2252**  FUNCTION VALUE:
2253**
2254**      binding_rep     A Binding Rep data structure containing the object
2255**                      UUID of an RPC as well as the location of the remote
2256**                      half of the RPC.
2257**
2258**  SIDE EFFECTS:       none
2259**
2260**--
2261**/
2262
2263PRIVATE rpc_binding_rep_t *rpc__binding_alloc
2264(
2265    boolean32               is_server,
2266    uuid_p_t                object_uuid,
2267    rpc_protocol_id_t       protocol_id,
2268    rpc_addr_p_t            rpc_addr,
2269    unsigned32              *status
2270)
2271{
2272    rpc_binding_rep_p_t     binding_rep;
2273    unsigned_char_p_t       endpoint = NULL;
2274    unsigned32              temp_status;
2275
2276    CODING_ERROR (status);
2277
2278    /*
2279     * get protocol service to allocate an empty binding rep
2280     */
2281    binding_rep = (*rpc_g_protocol_id[protocol_id].binding_epv
2282        ->binding_alloc) (is_server, status);
2283
2284    /*
2285     * Initialize the common part of the binding rep.
2286     */
2287    binding_rep->is_server = is_server;
2288    binding_rep->protocol_id = protocol_id;
2289    binding_rep->obj = *object_uuid;
2290    binding_rep->timeout = rpc_c_binding_default_timeout;
2291    binding_rep->ns_specific = NULL;
2292    binding_rep->auth_info = NULL;
2293    binding_rep->transport_info = NULL;
2294    binding_rep->bound_server_instance = false;
2295    binding_rep->addr_has_endpoint = false;
2296    binding_rep->refcnt = 1;            /* the reference we are returning */
2297    binding_rep->calls_in_progress = 0;
2298    binding_rep->call_timeout_time = 0;
2299    binding_rep->fork_count = rpc_g_fork_count;
2300    binding_rep->protocol_version = NULL;
2301    binding_rep->extended_bind_flag = RPC_C_BH_EXTENDED_NONE;
2302
2303    /*
2304     * By default, created bindings are declared to have dynamic
2305     * addresses; *this* default state is important.  Callers of
2306     * binding_alloc that know they're associating a non-dynamic
2307     * addr with the binding can change this state.
2308     */
2309    binding_rep->addr_is_dynamic = true;
2310
2311    if (rpc_addr != NULL)
2312    {
2313        /*
2314         * find out if the RPC address contains an endpoint
2315         */
2316        (*rpc_g_naf_id[rpc_addr->sa.family].epv->naf_addr_inq_endpoint)
2317            (rpc_addr, &endpoint, status);
2318
2319        /*
2320         * If the addr has an endpoint, tell everyone.
2321         */
2322        if (*status != rpc_s_ok)
2323        {
2324            /*
2325             * then ask the protocol service to free the binding rep and
2326             * NULL the reference.
2327             */
2328            (*rpc_g_protocol_id[protocol_id].binding_epv->binding_free)
2329                (&binding_rep, &temp_status);
2330				/* mdn 23.10.1999: FIXME if I am wrong
2331				 * if endpoint was allocated it is not a NULL pointer, so
2332				 * it must be freed. */
2333				/* return (NULL); */
2334				binding_rep = NULL;
2335				goto CLEANUP;
2336        }
2337        else
2338        {
2339            if (strlen ((char *) endpoint) != 0)
2340            {
2341                binding_rep->addr_has_endpoint = true;
2342            }
2343        }
2344    }
2345
2346    /*
2347     * set the pointer to the specified rpc address in the binding
2348     */
2349    binding_rep->rpc_addr = rpc_addr;
2350
2351    /*
2352     * get the protocol service to initialize the rest of the binding
2353     */
2354    (*rpc_g_protocol_id[protocol_id].binding_epv
2355        ->binding_init) (binding_rep, status);
2356
2357    *status = rpc_s_ok;
2358
2359CLEANUP:
2360
2361    if (endpoint != NULL)
2362    {
2363        rpc_string_free (&endpoint, &temp_status);
2364    }
2365
2366    return (binding_rep);
2367}
2368
2369/*
2370**++
2371**
2372**  ROUTINE NAME:       rpc_binding_inq_client
2373**
2374**  SCOPE:              PUBLIC
2375**
2376**  DESCRIPTION:
2377**
2378**  This routine returns a protocol service dependent client handle which
2379**  can be used by the stubs to identify a particular instance of a
2380**  particular client process.
2381**
2382**  INPUTS:
2383**
2384**      binding_h       Server stub binding handle
2385**
2386**  INPUTS/OUTPUTS:     none
2387**
2388**  OUTPUTS:
2389**
2390**      client_h        Client handle for use with monitor_liveness routine
2391**
2392**      status          A value indicating the status of the routine.
2393**            rpc_s_invalid_binding
2394**                          RPC Protocol ID in binding handle was invalid.
2395**
2396**
2397**
2398**  IMPLICIT INPUTS:    none
2399**
2400**  IMPLICIT OUTPUTS:   none
2401**
2402**  FUNCTION VALUE:
2403**
2404**      void
2405**
2406**  SIDE EFFECTS:       none
2407**
2408**--
2409**/
2410
2411PUBLIC void rpc_binding_inq_client
2412(
2413    rpc_binding_handle_t    binding_h,
2414    rpc_client_handle_t     *client_h,
2415    unsigned32              *status
2416)
2417{
2418    rpc_binding_rep_p_t binding_rep = (rpc_binding_rep_p_t) binding_h;
2419
2420    assert(binding_rep != NULL);
2421
2422    CODING_ERROR (status);
2423    RPC_VERIFY_INIT ();
2424
2425    RPC_BINDING_VALIDATE_SERVER(binding_rep, status);
2426    if (*status != rpc_s_ok)
2427        return;
2428
2429    /*
2430     * Ask the protocol service for a client handle associated with
2431     * the client on the other end of the connection specified by this
2432     * server binding handle.
2433     */
2434    (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
2435        ->binding_inq_client) (binding_rep, client_h, status);
2436}
2437
2438/*
2439**++
2440**
2441**  ROUTINE NAME:       rpc_binding_handle_copy
2442**
2443**  SCOPE:              PUBLIC
2444**
2445**  DESCRIPTION:
2446**
2447**  This routine creates a duplicate handle to an existing
2448**  (now shared) binding (via bumping a reference count).
2449**
2450**  INPUTS:
2451**
2452**      source_binding  The binding handle which points to the source
2453**                      binding rep data structure to be copied.
2454**
2455**  INPUTS/OUTPUTS:     none
2456**
2457**  OUTPUTS:
2458**
2459**      destination_binding
2460**                      The binding handle which points to the shared
2461**                      binding rep data structure.
2462**
2463**      status          A value indicating the status of the routine.
2464**
2465**          rpc_s_ok        The call was successful.
2466**          rpc_s_invalid_binding
2467**                          RPC Protocol ID in binding handle was invalid.
2468**          rpc_s_coding_error
2469**
2470**  IMPLICIT INPUTS:    none
2471**
2472**  IMPLICIT OUTPUTS:   none
2473**
2474**  FUNCTION VALUE:     void
2475**
2476**  SIDE EFFECTS:       none
2477**
2478**--
2479**/
2480
2481 void rpc_binding_handle_copy
2482(
2483    rpc_binding_handle_t    source_binding,
2484    rpc_binding_handle_t    *destination_binding,
2485    unsigned32              *status
2486)
2487{
2488    rpc_binding_rep_p_t     src_binding_rep = (rpc_binding_rep_p_t) source_binding;
2489    rpc_binding_rep_p_t     *dst_binding_rep =
2490                                (rpc_binding_rep_p_t *) destination_binding;
2491
2492    assert(src_binding_rep != NULL);
2493
2494    CODING_ERROR (status);
2495    RPC_VERIFY_INIT ();
2496
2497    RPC_BINDING_VALIDATE_CLIENT(src_binding_rep, status);
2498    if (*status != rpc_s_ok)
2499        return;
2500
2501    /*
2502     * Add a new reference.
2503     */
2504
2505    *dst_binding_rep = src_binding_rep;
2506
2507    RPC_LOCK(0);
2508    RPC_BINDING_REFERENCE(src_binding_rep);
2509    RPC_UNLOCK(0);
2510
2511    *status = rpc_s_ok;
2512}
2513
2514/*
2515**++
2516**
2517**  ROUTINE NAME:       rpc_binding_handle_equal
2518**
2519**  SCOPE:              PUBLIC
2520**
2521**  DESCRIPTION:
2522**
2523**  This routine compares two binding handles to determine if they
2524**  reference the same binding object.  The current external binding handle
2525**  representation (a pointer) doesn't really require the assistance
2526**  of such a function, however, it is anticipated that we will (shortly)
2527**  change the external representation to something that will allow us
2528**  to detect dangling references users will not be able to perform a
2529**  comparison via the C "==" operator.
2530**
2531**  INPUTS:
2532**
2533**      binding_h1      One binding handle ref.
2534**      binding_h2      A second binding handle ref.
2535**
2536**  INPUTS/OUTPUTS:     none
2537**
2538**  OUTPUTS:
2539**
2540**      status          A value indicating the status of the routine.
2541**
2542**          rpc_s_ok        The call was successful.
2543**
2544**  IMPLICIT INPUTS:    none
2545**
2546**  IMPLICIT OUTPUTS:   none
2547**
2548**  FUNCTION VALUE:
2549**
2550**      result          true if both handle's refer to the same binding rep
2551**                      false if they don't
2552**
2553**  SIDE EFFECTS:       none
2554**
2555**--
2556**/
2557
2558PUBLIC boolean32 rpc_binding_handle_equal
2559(
2560    rpc_binding_handle_t    binding1,
2561    rpc_binding_handle_t    binding2,
2562    unsigned32              *status
2563)
2564{
2565    CODING_ERROR (status);
2566    RPC_VERIFY_INIT ();
2567
2568    *status = rpc_s_ok;
2569
2570    return (binding1 == binding2);
2571}
2572
2573/*
2574**++
2575**
2576**  ROUTINE NAME:       rpc_binding_server_to_client
2577**
2578**  SCOPE:              PUBLIC - declared in rpcpvt.idl
2579**
2580**  DESCRIPTION:
2581**
2582**  This routine provides compatibility for DCE components that were
2583**  coded prior to the routine name change from rpc_binding_server_to_client()
2584**  to rpc_binding_server_from_client().
2585**
2586**  This routine calls through to the rpc_binding_server_from_client()
2587**  API routine.
2588**
2589**  	NOTE: This description uses old terminology.
2590**
2591**  Convert a server binding handle to a client handle.  The new handle's
2592**  endpoint is reset and it has no associated authentication information.
2593**
2594**  Server binding handles are those created by the runtime and provided
2595**  to the server manager as a result of a [handle_t] RPC parameter.
2596**
2597**  INPUTS:
2598**
2599**      src_binding_h   The binding handle which points to the (server)
2600**                      source binding rep data structure to be converted.
2601**
2602**  INPUTS/OUTPUTS:     none
2603**
2604**  OUTPUTS:
2605**
2606**      dst_binding_h   The binding handle which points to the converted (client)
2607**                      destination binding rep data structure.
2608**
2609**      status          A value indicating the status of the routine.
2610**
2611**          rpc_s_ok        The call was successful.
2612**          rpc_s_invalid_binding
2613**                          RPC Protocol ID in binding handle was invalid.
2614**          rpc_s_coding_error
2615**
2616**  IMPLICIT INPUTS:    none
2617**
2618**  IMPLICIT OUTPUTS:   none
2619**
2620**  FUNCTION VALUE:     void
2621**
2622**  SIDE EFFECTS:       none
2623**
2624**--
2625**/
2626
2627PUBLIC void rpc_binding_server_to_client
2628(
2629    rpc_binding_handle_t    src_binding_h,
2630    rpc_binding_handle_t    *dst_binding_h,
2631    unsigned32              *status
2632)
2633{
2634    rpc_binding_server_from_client (src_binding_h, dst_binding_h, status);
2635    return;
2636}
2637
2638/*
2639**++
2640**
2641**  ROUTINE NAME:       rpc_binding_server_from_client
2642**
2643**  SCOPE:              PUBLIC - declared in rpc.idl
2644**
2645**  DESCRIPTION:
2646**
2647**      NOTE: This description and the code use phrases "server binding
2648**            handle" and "client binding handle" opposite from the way
2649**            these are used in the API documentation. At some point, we
2650**            should change the code to match the documentation.
2651**
2652**  Convert a server binding handle to a client handle.  The new handle's
2653**  endpoint is reset and it has no associated authentication information.
2654**
2655**  Server binding handles are those created by the runtime and provided
2656**  to the server manager as a result of a [handle_t] RPC parameter.
2657**
2658**  INPUTS:
2659**
2660**      src_binding_h   The binding handle which points to the (server)
2661**                      source binding rep data structure to be converted.
2662**
2663**  INPUTS/OUTPUTS:     none
2664**
2665**  OUTPUTS:
2666**
2667**      dst_binding_h   The binding handle which points to the converted (client)
2668**                      destination binding rep data structure.
2669**
2670**      status          A value indicating the status of the routine.
2671**
2672**          rpc_s_ok        The call was successful.
2673**          rpc_s_invalid_binding
2674**                          RPC Protocol ID in binding handle was invalid.
2675**          rpc_s_coding_error
2676**
2677**  IMPLICIT INPUTS:    none
2678**
2679**  IMPLICIT OUTPUTS:   none
2680**
2681**  FUNCTION VALUE:     void
2682**
2683**  SIDE EFFECTS:       none
2684**
2685**--
2686**/
2687
2688PUBLIC void rpc_binding_server_from_client
2689(
2690    rpc_binding_handle_t    src_binding_h,
2691    rpc_binding_handle_t    *dst_binding_h,
2692    unsigned32              *status
2693    )
2694{
2695    rpc_binding_rep_p_t     src_binding_rep = (rpc_binding_rep_p_t) src_binding_h;
2696    rpc_binding_rep_p_t     dst_binding_rep;
2697    rpc_addr_p_t            rpc_addr;
2698    unsigned32              tmp_status;
2699    boolean                 have_addr = false;
2700
2701    assert(src_binding_rep != NULL);
2702
2703    CODING_ERROR (status);
2704    RPC_VERIFY_INIT ();
2705
2706    RPC_BINDING_VALIDATE_SERVER(src_binding_rep, status);
2707    if (*status != rpc_s_ok)
2708        return;
2709
2710    /*
2711     * if the RPC address in the source is NULL, get one from protocol service
2712     */
2713    if (src_binding_rep->rpc_addr == NULL)
2714    {
2715        rpc_addr_p_t srpc_addr;
2716
2717        (*rpc_g_protocol_id[src_binding_rep->protocol_id].binding_epv
2718         ->binding_inq_addr) (src_binding_rep, &srpc_addr, status);
2719
2720        if (*status != rpc_s_ok)
2721            return;
2722
2723        /*
2724         *  make a copy of the one in the source
2725         */
2726        (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv
2727            ->naf_addr_copy)
2728                (src_binding_rep->rpc_addr, &rpc_addr, status);
2729
2730    }
2731    else
2732    {
2733        /*
2734         * otherwise, make a copy of the one in the source
2735         */
2736        (*rpc_g_naf_id[src_binding_rep->rpc_addr->sa.family].epv
2737            ->naf_addr_copy)
2738                (src_binding_rep->rpc_addr, &rpc_addr, status);
2739        if (*status != rpc_s_ok) return;
2740    }
2741    have_addr = true;
2742
2743    /*
2744     * The resultant binding's address has no endpoint.  It is absolutely
2745     * wrong to use the originating client's endpoint.
2746     */
2747    rpc__naf_addr_set_endpoint ((unsigned_char_p_t) "", &rpc_addr, status);
2748    if (*status != rpc_s_ok) goto CLEANUP;
2749
2750    /*
2751     * allocate and init a *client* binding rep.
2752     */
2753    dst_binding_rep = rpc__binding_alloc (
2754        false, &src_binding_rep->obj,
2755        src_binding_rep->protocol_id, rpc_addr, status);
2756    if (*status != rpc_s_ok) goto CLEANUP;
2757
2758    /*
2759     * copy other common parts of the binding rep from the source to dest
2760     *
2761     * We explicitly leave the dst->auth NULL; the server (using this
2762     * new client handle) probably wants to make calls as its own
2763     * identity.
2764     */
2765    dst_binding_rep->timeout            = src_binding_rep->timeout;
2766    dst_binding_rep->call_timeout_time  = src_binding_rep->call_timeout_time;
2767    dst_binding_rep->addr_is_dynamic    = src_binding_rep->addr_is_dynamic;
2768
2769    /*
2770     * return the destination binding rep as a binding handle
2771     */
2772    *dst_binding_h = (rpc_binding_handle_t) dst_binding_rep;
2773
2774    *status = rpc_s_ok;
2775
2776CLEANUP:
2777
2778    if (*status != rpc_s_ok && have_addr)
2779        rpc__naf_addr_free (&rpc_addr, &tmp_status);
2780}
2781
2782
2783/*
2784**++
2785**
2786**  ROUTINE NAME:       rpc__binding_inq_sockaddr
2787**
2788**  SCOPE:              PRIVATE - declared in com.h
2789**
2790**  DESCRIPTION:
2791**
2792**  Inquire the sockaddr that is associated with a binding handle.
2793**
2794**  This is kernel RPC only (private) operation and exists strictly for
2795**  performance reasons.  The returned sockaddr pointer points to storage
2796**  directly associated with the binding handle.  This pointer can become
2797**  invalid under a number of circumstances (e.g. binding handle
2798**  operations); copy the sa if you need to use it after any binding handle
2799**  operations!
2800**
2801**  Note: Do NOT remove this routine even though it appears that nothing
2802**  is using it...  it is used by Kernel RPC Applications.
2803**
2804**  INPUTS:
2805**
2806**      binding_h       The binding handle which points to the binding
2807**                      rep data structure to be inquired.
2808**
2809**  INPUTS/OUTPUTS:     none
2810**
2811**  OUTPUTS:
2812**
2813**      sa              A pointer to the sockaddr contained in the binding.
2814**
2815**      status          A value indicating the status of the routine.
2816**
2817**          rpc_s_ok        The call was successful.
2818**
2819**  IMPLICIT INPUTS:    none
2820**
2821**  IMPLICIT OUTPUTS:   none
2822**
2823**  FUNCTION VALUE:     void
2824**
2825**  SIDE EFFECTS:       none
2826**
2827**--
2828**/
2829
2830PRIVATE void rpc__binding_inq_sockaddr
2831(
2832    rpc_binding_handle_t    binding_h,
2833    sockaddr_p_t            *sa,
2834    unsigned32              *status
2835)
2836{
2837    *sa = &((rpc_binding_rep_p_t) binding_h)->rpc_addr->sa;
2838
2839    *status = rpc_s_ok;
2840}
2841
2842/*
2843**++
2844**
2845**  ROUTINE NAME:       rpc__binding_cross_fork
2846**
2847**  SCOPE:              PRIVATE - declared in com.h
2848**
2849**  DESCRIPTION:
2850**
2851**  Perform whatever actions are required to make a binding handle usable
2852**  in the client of a fork.
2853**
2854**  Currently there is no common processing performed, and we just pass
2855**  the binding rep to protocol specific routines for processing.
2856**
2857**  INPUTS:
2858**
2859**      binding_rep     A pointer to a binding rep which is being used
2860**                      across a fork.
2861**
2862**  INPUTS/OUTPUTS:     none
2863**
2864**  OUTPUTS:
2865**
2866**      status          A value indicating the status of the routine.
2867**
2868**          rpc_s_ok        The call was successful.
2869**
2870**  IMPLICIT INPUTS:    none
2871**
2872**  IMPLICIT OUTPUTS:   none
2873**
2874**  FUNCTION VALUE:     void
2875**
2876**  SIDE EFFECTS:       Any state associated with the binding handle is
2877**                      dropped so that it is not inherited by the child
2878**                      of a fork.
2879**
2880**--
2881**/
2882
2883PRIVATE void rpc__binding_cross_fork
2884(
2885  rpc_binding_rep_p_t binding_rep,
2886  unsigned32 * status
2887)
2888{
2889    /*
2890     * Servers aren't allowed to fork, so we only allow passing
2891     * client binding handles across the fork.
2892     */
2893    if (! RPC_BINDING_IS_CLIENT(binding_rep))
2894    {
2895        *status = rpc_s_wrong_kind_of_binding;
2896        return;
2897    }
2898
2899    /*
2900     * We only want to bring the handle across the fork once.
2901     * Take the global lock, then check that the handle still
2902     * needs to cross the fork.
2903     */
2904    RPC_LOCK(0);
2905
2906    if (binding_rep->fork_count != rpc_g_fork_count)
2907    {
2908        /*
2909         * Ask the protocol service to clean up any protocol specific
2910         * state that should not survive in the child of a fork.
2911         */
2912        (*rpc_g_protocol_id[binding_rep->protocol_id].binding_epv
2913           ->binding_cross_fork) (binding_rep, status);
2914
2915        /*
2916         * Update the handle to the current fork count.
2917         */
2918        binding_rep->fork_count = rpc_g_fork_count;
2919    }
2920
2921    RPC_UNLOCK(0);
2922}
2923
2924/*
2925**++
2926**  ROUTINE NAME:       rpc__binding_prot_version_alloc
2927**
2928**  SCOPE:              PRIVATE
2929**
2930**  DESCRIPTION:
2931**
2932**  Allocates and initializes an rpc_protocol_version_t struct.
2933**
2934**  INPUTS:
2935**      major_version       The major version of the protocol
2936**
2937**      minor_version       The minor version of the protocol.
2938**
2939**
2940**  OUTPUTS:
2941**      prot_version        The allocated protocol_version structure.
2942**
2943**      status
2944**                          rpc_s_ok
2945**
2946**
2947**  IMPLICIT INPUTS:    none
2948**
2949**  IMPLICIT OUTPUTS:   none
2950**
2951**  FUNCTION VALUE:     void
2952**
2953**  SIDE EFFECTS:       none
2954**
2955**--
2956*/
2957PRIVATE void rpc__binding_prot_version_alloc(
2958    rpc_protocol_version_p_t    *prot_version,
2959    unsigned32		        major_version,
2960    unsigned32		        minor_version,
2961    unsigned32		        *status)
2962
2963{
2964
2965    /*
2966     * Alocate a version struct
2967     */
2968    RPC_MEM_ALLOC(*prot_version,
2969                  rpc_protocol_version_p_t,
2970                  sizeof(rpc_protocol_version_t),
2971                  RPC_C_MEM_PROTOCOL_VERSION,
2972                  RPC_C_MEM_WAITOK);
2973
2974    /*
2975     * Initialize data
2976     */
2977    (*prot_version)->major_version = major_version;
2978    (*prot_version)->minor_version = minor_version;
2979
2980    *status = rpc_s_ok;
2981
2982    return;
2983}
2984
2985
2986/*
2987**++
2988**  ROUTINE NAME:       rpc__binding_prot_version_free
2989**
2990**  SCOPE:              PRIVATE - declared in com.h
2991**
2992**  DESCRIPTION:
2993**
2994**  Free's an rpc_protocol_version_t struct.
2995**  The pointer is set to NULL.
2996**
2997**  INPUTS:
2998**    protocol_version  Pointer to the version stuct.
2999**
3000**
3001**  OUTPUTS:            none
3002**
3003**  SIDE EFFECTS:       none
3004**
3005**--
3006*/
3007PRIVATE void rpc__binding_prot_version_free(
3008    rpc_protocol_version_p_t		*protocol_version)
3009
3010{
3011    RPC_MEM_FREE (*protocol_version, RPC_C_MEM_PROTOCOL_VERSION);
3012    *protocol_version = NULL;
3013
3014    return;
3015}
3016
3017
3018/*
3019**++
3020**  ROUTINE NAME:       rpc__binding_set_prot_version
3021**
3022**  SCOPE:              PRIVATE - called from nslookup.c
3023**
3024**  DESCRIPTION:
3025**
3026**  Sets the protocol version in a binding_rep data structure
3027**  from a protocol tower.
3028**
3029**  INPUTS:
3030**      binding_h       The binding handle which points to the binding
3031**                      rep data structure to be modified.
3032**
3033**      tower_ref	The tower to get the protocol version information
3034**
3035**  OUTPUTS:
3036**      status          return status from called routines.
3037**
3038**  SIDE EFFECTS:       none
3039**
3040**--
3041*/
3042PRIVATE void rpc__binding_set_prot_version(
3043    rpc_binding_handle_t                binding_h,
3044    rpc_tower_ref_p_t                   tower_ref,
3045    unsigned32                          *status)
3046{
3047    rpc_binding_rep_p_t     binding_rep;
3048    rpc_protocol_id_t       temp_protocol_id;
3049    unsigned32              major_version;
3050    unsigned32              minor_version;
3051
3052    /*
3053     * Get the major and minor version of the tower.
3054     */
3055    rpc__tower_flr_to_rpc_prot_id(tower_ref->floor[2],
3056                                  &temp_protocol_id,
3057                                  &major_version,
3058                                  &minor_version,
3059                                  status);
3060
3061    if (*status != rpc_s_ok)
3062    {
3063        return;
3064    }
3065
3066    /*
3067     * Allocate a protocol structure and initialize it.
3068     */
3069    binding_rep = (rpc_binding_rep_p_t) binding_h;
3070    rpc__binding_prot_version_alloc(&(binding_rep->protocol_version),
3071                                    major_version,
3072                                    minor_version,
3073                                    status);
3074
3075    return;
3076}
3077
3078
3079/*
3080**++
3081**  ROUTINE NAME:       rpc_binding_create
3082**
3083**  SCOPE:              PUBLIC
3084**
3085**  DESCRIPTION:
3086**
3087**  INPUTS:
3088**      template        binding handle template
3089**
3090**      security        security options
3091**
3092**      options         other options
3093**
3094**  OUTPUTS:
3095**      binding_h       binding handle
3096**
3097**      status          return status from called routines.
3098**
3099**  SIDE EFFECTS:       none
3100**
3101**--
3102*/
3103PUBLIC void rpc_binding_create(
3104    rpc_binding_handle_template_t       *template,
3105    rpc_binding_handle_security_t       *security,
3106    rpc_binding_handle_options_t        *options,
3107    rpc_binding_handle_t                *binding_h,
3108    unsigned32                          *st)
3109{
3110    unsigned_char_p_t			string_object_uuid = NULL;
3111    unsigned_char_p_t			string_binding = NULL;
3112    rpc_binding_handle_t		h = NULL;
3113    unsigned32				tmp_st;
3114
3115    CODING_ERROR(st);
3116
3117    *binding_h = NULL;
3118
3119    if (template->version != 1 ||
3120        (security != NULL && security->version != 1) ||
3121        (options != NULL && options->version != 1))
3122    {
3123	*st = rpc_s_rpc_prot_version_mismatch; /* XXX */
3124	return;
3125    }
3126
3127    if (!uuid_is_nil(&template->object_uuid, st))
3128    {
3129	uuid_to_string(&template->object_uuid, &string_binding, st);
3130	if (*st != rpc_s_ok)
3131	    return;
3132    }
3133
3134    rpc_string_binding_compose(string_object_uuid,
3135			       template->protseq,
3136			       template->network_address,
3137			       template->string_endpoint,
3138			       template->reserved,
3139			       &string_binding,
3140			       st);
3141    rpc_string_free(&string_object_uuid, &tmp_st);
3142    if (*st != rpc_s_ok)
3143	return;
3144
3145    rpc_binding_from_string_binding(string_binding, &h, st);
3146    rpc_string_free(&string_binding, &tmp_st);
3147    if (*st != rpc_s_ok)
3148	return;
3149
3150    if (*st == rpc_s_ok && h == NULL)
3151    {
3152	*st = rpc_s_no_bindings;
3153	return;
3154    }
3155
3156    if (options != NULL)
3157    {
3158	rpc_mgmt_set_com_timeout(h, options->com_timeout, st);
3159	if (*st != rpc_s_ok)
3160	{
3161	    rpc_binding_free(&h, &tmp_st);
3162	    return;
3163	}
3164	rpc_mgmt_set_cancel_timeout(options->cancel_timeout, st);
3165	if (*st != rpc_s_ok)
3166	{
3167	    rpc_binding_free(&h, &tmp_st);
3168	    return;
3169	}
3170    }
3171
3172    if (security != NULL)
3173    {
3174	rpc_binding_set_auth_info(h,
3175				  security->server_princ_name,
3176				  security->authn_level,
3177				  security->authn_protocol,
3178				  security->auth_identity,
3179				  security->authz_svc,
3180				  st);
3181	if (*st != rpc_s_ok)
3182	{
3183	    rpc_binding_free(&h, &tmp_st);
3184	    return;
3185	}
3186    }
3187
3188    *binding_h = h;
3189
3190    return;
3191}
3192