1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**
80**  NAME:
81**
82**    COMTWR.C
83**
84**  FACILITY:
85**
86**    Remote procedure call (RPC)
87**
88**  ABSTRACT:
89**
90**  Set of routines supporting operations that create and manipulate the
91**  canonical representation of a protocol tower.
92**
93**
94**/
95
96#include <commonp.h>    /* Private defs for Common component            */
97#include <com.h>        /* Private COM defs for other RPC components    */
98#include <comp.h>       /* Privates for COM Services component          */
99#include <comtwr.h>     /* Private tower defs                           */
100#include <comtwrref.h>  /* Private tower ref defs for other RPC components */
101
102
103/*
104**++
105**  ROUTINE NAME:       rpc__tower_free
106**
107**  SCOPE:              PRIVATE - declared in comtwr.h
108**
109**  DESCRIPTION:
110**
111**  Releases memory used by a tower that was dynamically created.
112**  Towers are dynamically created by calling the
113**  rpc__tower_from_tower_ref routine.
114**
115**  INPUTS:             none
116**
117**  INPUT/OUTPUTS:
118**
119**      tower           Canonical representation of a protocol tower.
120**                      Nulled on return.
121**
122**  OUTPUTS:
123**
124**      status          Returns the status code from the free
125**                      operation. This status code indicates whether the
126**                      routine completed successfully and, if not, why.
127**                      Returns rpc_s_ok.
128**
129**  IMPLICIT INPUTS:    none
130**
131**  IMPLICIT OUTPUTS:   none
132**
133**  FUNCTION VALUE:     none
134**
135**  SIDE EFFECTS:       none
136**
137**--
138*/
139
140PRIVATE void rpc__tower_free
141(
142    twr_p_t             *tower,
143    unsigned32          *status
144)
145{
146    CODING_ERROR (status);
147
148    RPC_MEM_FREE (*tower, RPC_C_MEM_TOWER);
149    *tower = NULL;
150
151    *status = rpc_s_ok;
152    return;
153}
154
155
156/*
157**++
158**  ROUTINE NAME:       rpc__tower_from_tower_ref
159**
160**  SCOPE:              PRIVATE - declared in comtwr.h
161**
162**  DESCRIPTION:
163**
164**  This routine creates the canonical representation of a protocol tower
165**  from a runtime reference representation of a protocol tower.
166**
167**  INPUTS:
168**
169**      tower_ref       Runtime reference representation of a protocol tower.
170**
171**  INPUT/OUTPUTS:      none
172**
173**  OUTPUTS:
174**
175**      tower           Returns a pointer to the canonical representation
176**                      of a protocol tower.
177**
178**      status          Returns the status code from the
179**                      tower from tower_ref operation. This status code
180**                      indicates whether the routine completed
181**                      successfully and, if not, why.
182**                      Returns
183**                          rpc_s_ok
184**                      or status from a called routine.
185**
186**  IMPLICIT INPUTS:    none
187**
188**  IMPLICIT OUTPUTS:   none
189**
190**  FUNCTION VALUE:
191**
192**      void
193**
194**  SIDE EFFECTS:       none
195**
196**--
197*/
198
199PRIVATE void rpc__tower_from_tower_ref
200(
201    rpc_tower_ref_p_t       tower_ref,
202    twr_p_t                 *tower,
203    unsigned32              *status
204)
205{
206    byte_p_t                tower_p;
207    unsigned16              twr_rep_16;
208    unsigned32              i,
209                            floor_size,
210                            octet_length;
211
212    /*
213     * Calculate the size of the tower octet string.
214     */
215    for (i = 0, octet_length = 0;
216         i < tower_ref->count; i++)
217    {
218        octet_length += (tower_ref->floor[i]->prot_id_count +
219                         RPC_C_TOWER_FLR_LHS_COUNT_SIZE +
220                         tower_ref->floor[i]->address_count +
221                         RPC_C_TOWER_FLR_RHS_COUNT_SIZE);
222    }
223
224    octet_length += RPC_C_TOWER_FLR_COUNT_SIZE;
225
226    /*
227     * Allocate the tower structure to hold the
228     * canonical representation of the tower.
229     */
230    RPC_MEM_ALLOC (
231        *tower,
232        twr_p_t,
233        sizeof (twr_t) + octet_length - 1,
234        RPC_C_MEM_TOWER, RPC_C_MEM_WAITOK );
235
236    /*
237     * Initialize the tower length in the tower structure.
238     */
239    (*tower)->tower_length = octet_length;
240
241    /*
242     * Form the tower octet string starting
243     * with the tower floor count size.
244     */
245    tower_p = (*tower)->tower_octet_string;
246
247    /*
248     * Convert the tower count to little endian
249     * and copy it to the octet string.
250     */
251    twr_rep_16 = tower_ref->count;
252    RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16);
253    memcpy ((char *)tower_p,
254            (char *)&twr_rep_16, RPC_C_TOWER_FLR_COUNT_SIZE);
255
256    tower_p += RPC_C_TOWER_FLR_COUNT_SIZE;
257
258    /*
259     * And now copy each tower floor to the octet string.
260     */
261    for (i=0; i < tower_ref->count; i++)
262    {
263        floor_size =
264            RPC_C_TOWER_FLR_LHS_COUNT_SIZE  +
265            tower_ref->floor[i]->prot_id_count +
266            RPC_C_TOWER_FLR_RHS_COUNT_SIZE  +
267            tower_ref->floor[i]->address_count;
268
269        memcpy ((char *)tower_p, (char *)tower_ref->floor[i]->octet_string,
270                floor_size);
271
272        tower_p += floor_size;
273    }
274
275    *status = rpc_s_ok;
276    return;
277}
278
279
280/*
281**++
282**  ROUTINE NAME:       rpc__tower_to_tower_ref
283**
284**  SCOPE:              PRIVATE - declared in comtwr.h
285**
286**  DESCRIPTION:
287**
288**  Creates a runtime reference representation of a protocol tower
289**  from a canonical representation of a protocol tower.
290**
291**  INPUTS:
292**
293**      tower           Canonical representation of a protocol tower.
294**
295**  INPUT/OUTPUTS:      none
296**
297**  OUTPUTS:
298**
299**      tower_ref       Returns a pointer to a reference representation
300**                      of a protocol tower.
301**      status          Returns the status code from the tower to tower ref
302**                      operation. This status code indicates whether the
303**                      routine completed successfully and, if not, why.
304**                      Returns
305**                          rpc_s_ok
306**                      or status from a called routine.
307**
308**  IMPLICIT INPUTS:    none
309**
310**  IMPLICIT OUTPUTS:   none
311**
312**  FUNCTION VALUE:     void
313**
314**  SIDE EFFECTS:       none
315**
316**--
317*/
318
319PRIVATE void rpc__tower_to_tower_ref
320(
321    twr_p_t             tower,
322    rpc_tower_ref_p_t   *tower_ref,
323    unsigned32          *status
324)
325{
326    unsigned16              floor_count;
327
328    CODING_ERROR (status);
329
330    /*
331     * Get the tower floor count and correct for proper endian.
332     */
333    memcpy ((char *) &floor_count, (char *) tower->tower_octet_string,
334            RPC_C_TOWER_FLR_COUNT_SIZE);
335    RPC_RESOLVE_ENDIAN_INT16 (floor_count);
336
337    /*
338     * Allocate and initialize the tower reference structure to be returned.
339     */
340    rpc__tower_ref_alloc (tower->tower_octet_string, floor_count, 1,
341        tower_ref, status);
342
343    /*
344     * Return status from the tower ref allocate operation.
345     */
346    return;
347}
348
349
350/*
351**++
352**  ROUTINE NAME:       rpc_tower_to_binding
353**
354**  SCOPE:              PUBLIC - declared in rpc.idl
355**
356**  DESCRIPTION:
357**
358**  Creates a binding handle from a canonical representation of a
359**  protocol tower.  After the caller is finished with the binding, the
360**  rpc_binding_free routine must be called to release the memory used
361**  by the binding.
362**
363**  Note, this is an SPI routine - available to outside the runtime,
364**  but only to other DCE components.
365**
366**  INPUTS:
367**
368**      prot_tower          A single protocol tower (DNA$Tower attribute value)
369**                          to convert to a binding handle.
370**
371**  INPUT/OUTPUTS:          none
372**
373**  OUTPUTS:
374**
375**      binding             Returns a binding handle.
376**      status              Returns the status code from the tower-to-binding
377**                          operation. This status code indicates whether the
378**                          routine completed successfully and, if not, why.
379**                          Returns
380**                              rpc_s_ok
381**                          or status from a called routine.
382**
383**  IMPLICIT INPUTS:        none
384**
385**  IMPLICIT OUTPUTS:       none
386**
387**  FUNCTION VALUE:         void
388**
389**  SIDE EFFECTS:           none
390**
391**--
392*/
393
394PUBLIC void rpc_tower_to_binding
395(
396    byte_p_t                prot_tower,
397    rpc_binding_handle_t    *binding,
398    unsigned32              *status
399)
400{
401    rpc_binding_rep_p_t     binding_rep;
402    rpc_protocol_id_t       prot_id;
403    rpc_addr_p_t            rpc_addr;
404
405    CODING_ERROR (status);
406    RPC_VERIFY_INIT ();
407
408    /*
409     * Null binding in case of error before finishing.
410     */
411    *binding = NULL;
412
413    /*
414     * Obtain an RPC address for the tower.
415     */
416    rpc__naf_tower_flrs_to_addr (prot_tower, &rpc_addr, status);
417    if (*status != rpc_s_ok)
418    {
419        return;
420    }
421
422    prot_id = RPC_PROTSEQ_INQ_PROT_ID(rpc_addr->rpc_protseq_id);
423
424    /*
425     * Allocate and initialize a binding rep.
426     */
427    binding_rep = rpc__binding_alloc
428                    (false, &uuid_g_nil_uuid, prot_id, rpc_addr, status);
429
430    /*
431     * Return binding handle to user.
432     */
433    *binding = (rpc_binding_handle_t) binding_rep;
434
435    /*
436     * Return status from rpc__binding_alloc
437     */
438    return;
439
440}
441
442
443/*
444**++
445**  ROUTINE NAME:       rpc_tower_vector_from_binding
446**
447**  SCOPE:              PUBLIC - declared in rpc.idl
448**
449**  DESCRIPTION:
450**
451**  Creates a vector of twr_t's from a binding handle. After the caller is
452**  finished with the tower vector, the rpc_tower_vector_free routine must be
453**  called to release the memory used by the vector.
454**
455**  Note, this is an SPI routine - available to outside the runtime,
456**  but only to other DCE components.
457**
458**  INPUTS:
459**
460**      if_spec             Interface spec to combine with a binding
461**                          handle to form a tower vector.
462**
463**      binding             Binding handle to combine with an interface
464**                          spec to form a tower vector.
465**
466**  INPUT/OUTPUTS:          none
467**
468**  OUTPUTS:
469**
470**      tower_vector        Returns an allocated tower vector.
471**
472**      status              Returns the status code from the
473**                          tower-vector-from-binding operation.
474**                          This status code indicates whether the
475**                          routine completed successfully and, if not, why.
476**                          Returns
477**                              rpc_s_ok
478**                              rpc_s_no_interfaces
479**                          or status from a called routine.
480**
481**  IMPLICIT INPUTS:        none
482**
483**  IMPLICIT OUTPUTS:       none
484**
485**  FUNCTION VALUE:         void
486**
487**  SIDE EFFECTS:           none
488**
489**--
490*/
491
492PUBLIC void rpc_tower_vector_from_binding
493(
494    rpc_if_handle_t         if_spec,
495    rpc_binding_handle_t    binding,
496    rpc_tower_vector_p_t    *twr_vector,
497    unsigned32              *status
498)
499{
500    rpc_tower_ref_vector_t  *tower_ref_vector;
501    unsigned int                      i;
502    unsigned32               temp_status;
503
504    CODING_ERROR (status);
505    RPC_VERIFY_INIT ();
506
507    /*
508     * Null the twr_vector in case of error before finishing.
509     */
510    *twr_vector = NULL;
511
512    if (if_spec == NULL)
513    {
514        *status = rpc_s_no_interfaces;
515        return;
516    }
517
518    /*
519     * Convert the binding to a vector of tower refs.
520     */
521
522    rpc__tower_ref_vec_from_binding ((rpc_if_rep_p_t)if_spec, binding,
523        &tower_ref_vector, status);
524
525    if (*status != rpc_s_ok)
526    {
527        /*
528         * No need to goto CLEANUP; since a tower_ref_vector wasn't
529         * returned to us.
530         */
531        return;
532    }
533
534    /*
535     * Allocate a rpc_tower_vector_t based on the number of returned
536     * tower refs.
537     */
538    RPC_MEM_ALLOC (
539        *twr_vector,
540        rpc_tower_vector_p_t,
541        sizeof (rpc_tower_vector_t) + (tower_ref_vector->count - 1) *
542            sizeof (twr_p_t),
543        RPC_C_MEM_TOWER_VECTOR,
544        RPC_C_MEM_WAITOK );
545
546    (*twr_vector)->count = tower_ref_vector->count;
547
548    /*
549     * For each returned tower ref convert the tower ref to a twr_t and
550     * store the twr_t in the rpc_tower_vector_t.
551     */
552    for (i = 0; i < tower_ref_vector->count; i++)
553    {
554        rpc__tower_from_tower_ref (tower_ref_vector->tower[i],
555            &(*twr_vector)->tower[i], status);
556
557        if (*status != rpc_s_ok)
558        {
559            RPC_MEM_FREE (*twr_vector, RPC_C_MEM_TOWER_VECTOR);
560
561            goto CLEANUP;
562        }
563    }
564
565CLEANUP:
566    /*
567     * Free the tower_ref_vector returned from
568     * rpc__tower_ref_vec_from_binding().
569     */
570    rpc__tower_ref_vec_free (&tower_ref_vector, &temp_status);
571
572    /*
573     * If we got this far successfully, return whatever the result from
574     * rpc__tower_ref_vec_free(). Otherwise, return the previous error
575     * in status.
576     */
577    if (*status == rpc_s_ok)
578    {
579        *status = temp_status;
580    }
581
582    return;
583}
584
585/*
586**++
587**  ROUTINE NAME:       rpc_tower_vector_free
588**
589**  SCOPE:              PRIVATE - declared in comtwrref.h
590**
591**  DESCRIPTION:
592**
593**  Releases memory associated with a tower vector,
594**  including the towers as well as the vector.
595**
596**  INPUTS:             none
597**
598**  INPUT/OUTPUTS:
599**
600**      twr_vector      The tower vector to free. Nulled on return.
601**
602**  OUTPUTS:
603**
604**      status          Returns the status code from the tower free
605**                      operation. This status code is a value that
606**                      indicates whether the routine completed
607**                      successfully and, if not, why.
608**                      Returns
609**                          rpc_s_ok
610**                          or status from a called routine.
611**
612**  IMPLICIT INPUTS:    none
613**
614**  IMPLICIT OUTPUTS:   none
615**
616**  FUNCTION VALUE:     void
617**
618**  SIDE EFFECTS:       none
619**
620**--
621*/
622
623PRIVATE void rpc_tower_vector_free
624(
625    rpc_tower_vector_p_t    *twr_vector,
626    unsigned32              *status
627)
628{
629    unsigned32      i;
630
631    CODING_ERROR (status);
632
633    /*
634     * Free each tower reference in the vector.
635     */
636    for (i=0; i < (*twr_vector)->count; i++)
637    {
638        rpc__tower_free (&((*twr_vector)->tower[i]), status);
639        if (*status != rpc_s_ok)
640        {
641            return;
642        }
643    }
644
645    /*
646     * Free the tower vector structure and set pointer to NULL.
647     */
648    RPC_MEM_FREE (*twr_vector, RPC_C_MEM_TOWER_VECTOR);
649
650    *twr_vector = NULL;
651
652    *status = rpc_s_ok;
653    return;
654}
655