1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME
80**
81**      twr_dnet.c
82**
83**  FACILITY:
84**
85**      Protocol Tower Services for the DECnet address family
86**
87**  ABSTRACT:
88**
89**      The protocol tower service provides routines that:
90**
91**      o  convert a socket address to the lower floors of
92**         a protocol tower
93**
94**      o  convert a protocol tower to a socket address
95**
96**
97*/
98
99#include <commonp.h>    /* Common declarations for all RPC runtime */
100#if NAF_DNET
101#include <com.h>        /* Common communications services */
102#include <twrp.h>	/* Private tower services */
103
104/*
105 *  Include the DECnet specific socket address
106 */
107#ifdef unix
108#include <netdnet/dn.h>
109#else
110#include <dn.h>
111#endif
112
113/*
114**++
115**
116**  ROUTINE NAME:       twr_dnet_lower_flrs_from_sa
117**
118**  SCOPE:              PUBLIC - declared in twr.idl
119**
120**  DESCRIPTION:
121**
122**  Creates the canonical representation of a DECnet protocol tower's
123**  lower floors from a sockadddr. The canonical form can be transmitted
124**  on the wire, or included in a DNA tower.
125**
126**  INPUTS:
127**
128**      sa              DECnet-specific socket address data structure.
129**
130**  INPUTS/OUTPUTS:     none
131**
132**  OUTPUTS:
133**
134**      lower_flrs      Returns the lower tower floors in a twr_t
135**                      structure (includes the floor count as the first
136**                      field of "tower_octet_string" member).
137**
138**      status          A value indicating the return status of the routine:
139**                          twr_s_ok
140**                          twr_s_unknown_sa
141**
142**  IMPLICIT INPUTS:    none
143**
144**  IMPLICIT OUTPUTS:   none
145**
146**  FUNCTION VALUE:     void
147**
148**  SIDE EFFECTS:       none
149**
150**--
151**/
152
153PUBLIC void twr_dnet_lower_flrs_from_sa
154(
155    sockaddr_p_t      sa,
156    twr_p_t           *lower_flrs,
157    unsigned32        *status
158)
159{
160    unsigned8   protocol_id[TWR_C_NUM_DNA_LOWER_FLRS];
161    unsigned16  floor_count,
162                id_size = twr_c_tower_prot_id_size,
163                related_data_size[TWR_C_NUM_DNA_LOWER_FLRS],
164                twr_rep_16;
165    unsigned32  count,
166                twr_t_length,
167                *related_data_ptr[TWR_C_NUM_DNA_LOWER_FLRS];
168    byte_p_t    tmp_tower;
169
170    CODING_ERROR (status);
171    RPC_VERIFY_INIT ();
172
173    if (sa->family == RPC_C_NAF_ID_DNET)
174    {
175        protocol_id[0] = TWR_C_FLR_PROT_ID_DNA;
176        protocol_id[1] = TWR_C_FLR_PROT_ID_NSP;
177        protocol_id[2] = TWR_C_FLR_PROT_ID_ROUTING;
178
179        /*
180         * Since we now know the socket address we're dealing with,
181         * collect the sizes of each field to allocate memory, and
182         * remember the pointers to the fields so we can copy the
183         * data once we have allocated the tower string.
184         */
185
186        floor_count = TWR_C_NUM_DNA_LOWER_FLRS;
187
188        related_data_size[0] =
189        sizeof(((struct sockaddr_dn *)sa)->sdn_objnum) +
190        sizeof(((struct sockaddr_dn *)sa)->sdn_objnamel) +
191        ((struct sockaddr_dn *)sa)->sdn_objnamel;
192
193        related_data_ptr[0] =
194        (unsigned32 *)(&((struct sockaddr_dn *)sa)->sdn_objnum);
195
196        /*      do we need to store flags ???
197         *                related_data_size[1] =
198         *                   sizeof(((struct sockaddr_dn *)sa)->sdn_flags);
199         */
200        related_data_size[1] = 0;
201
202        related_data_ptr[1] =
203        (unsigned32 *)(&((struct sockaddr_dn *)sa)->sdn_flags);
204
205        related_data_size[2] =
206        sizeof(((struct sockaddr_dn *)sa)->sdn_add.a_len) +
207        ((struct sockaddr_dn *)sa)->sdn_add.a_len;
208
209        related_data_ptr[2] =
210        (unsigned32 *)(&((struct sockaddr_dn *)sa)->sdn_add);
211    }
212    else
213    {
214        *status = twr_s_unknown_sa;
215        return;
216    }
217
218    /*
219     * Allocate memory and copy the data into the proper
220     * locations in each of up to three floors.
221     */
222
223    /*
224     * Calculate length of tower floor.
225     */
226
227    twr_t_length = twr_c_tower_flr_count_size; /* to store floor count */
228
229    for ( count = 0; count < floor_count; count++ )
230    {
231        twr_t_length += TWR_C_FLR_OVERHEAD;
232        twr_t_length += related_data_size[count];
233    }
234
235    /*
236     * Next allocate space for the tower structure
237     */
238    RPC_MEM_ALLOC (
239        *lower_flrs,
240        twr_p_t,
241        sizeof (twr_t) + (twr_t_length - 1),
242        RPC_C_MEM_TOWER,
243        RPC_C_MEM_WAITOK );
244
245    /*
246     * Copy the length of the tower octet string into the tower structure
247     */
248    (*lower_flrs)->tower_length = twr_t_length;
249
250    /*
251     * Copy the floor information into the tower octet string
252     */
253
254    /*
255     * Use a temporary for the octet string since we need
256     * to increment the pointer.
257     */
258    tmp_tower = (*lower_flrs)->tower_octet_string;
259
260    /*
261     * Copy the number of floors into the tower octet string
262     */
263    twr_rep_16 = floor_count;
264    RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16);
265    memcpy ((char *)tmp_tower, (char *)&twr_rep_16,
266            twr_c_tower_flr_count_size);
267
268    tmp_tower += twr_c_tower_flr_count_size;
269
270    /*
271     * Convert the protocol identifier size to its proper
272     * representation for use in the following loop.
273     */
274    RPC_RESOLVE_ENDIAN_INT16 (id_size);
275
276    for (count = 0; count < floor_count; count++)
277    {
278        /*
279         * Copy the length of the protocol identifier field into
280         * tower octet string. (Converted before the loop.)
281         */
282        memcpy ((char *)tmp_tower, (char *)&id_size,
283                TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
284
285        tmp_tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE;
286
287        /*
288         * Copy the protocol identifier into tower octet string
289         * (1 byte so no need to convert endian representation).
290         */
291        memcpy ((char *)tmp_tower, (char *)&(protocol_id[count]),
292                twr_c_tower_prot_id_size);
293
294        tmp_tower += twr_c_tower_prot_id_size;
295
296        /*
297         * Copy the length of the address data field into
298         * tower octet string.
299         */
300        twr_rep_16 = related_data_size[count];
301        RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16);
302        memcpy ((char *)tmp_tower, (char *)&twr_rep_16,
303                TWR_C_TOWER_FLR_RHS_COUNT_SIZE);
304
305        tmp_tower += TWR_C_TOWER_FLR_RHS_COUNT_SIZE;
306
307        /*
308         * If there is addressing data, copy the address data field into
309         * tower octet string
310         */
311        if (related_data_size[count])
312        {
313            memcpy ((char *)tmp_tower, (char *)related_data_ptr[count],
314                    related_data_size[count] );
315
316            /*
317             * Set up for the next floor.
318             */
319            tmp_tower += related_data_size[count];
320        }
321    }
322
323    *status = twr_s_ok;
324}
325
326/*
327**++
328**
329**  ROUTINE NAME:       twr_dnet_lower_flrs_to_sa
330**
331**  SCOPE:              PUBLIC - declared in twr.idl
332**
333**  DESCRIPTION:
334**
335**  Creates a DECnet sockaddr from the canonical representation of a
336**  DECnet protocol tower's lower floors.
337**
338**  INPUTS:
339**
340**      tower_octet_string
341**                      The protocol tower to convert to a sockaddr.
342**
343**  INPUTS/OUTPUTS:     none
344**
345**  OUTPUTS:
346**
347**      sa            Returns a pointer to the created sockaddr structure.
348**
349**      sa_len          Returns the length, in bytes, of the returned
350**                      "sa" argument.
351**
352**      status          A value indicating the return status of the routine:
353**                          twr_s_ok
354**                          twr_s_unknown_tower
355**
356**  IMPLICIT INPUTS:    none
357**
358**  IMPLICIT OUTPUTS:   none
359**
360**  FUNCTION VALUE:     void
361**
362**  SIDE EFFECTS:       none
363**
364**--
365**/
366
367PUBLIC void twr_dnet_lower_flrs_to_sa
368(
369    byte_p_t          tower_octet_string,
370    sockaddr_p_t      *sa,
371    unsigned32        *sa_len,
372    unsigned32        *status
373)
374{
375    unsigned8   id;
376    byte_p_t    tower;
377    unsigned16  count,
378                floor_count,
379                id_size,
380                addr_size;
381    unsigned32  length;
382
383    CODING_ERROR (status);
384    RPC_VERIFY_INIT ();
385
386    id_size = 0;
387
388    /*
389     * make sure we have a pointer to some data structure
390     */
391    if ( !(tower = tower_octet_string))
392    {
393        *status = twr_s_unknown_tower;
394        return;
395    }
396
397    /*
398     * Get the tower floor count
399     */
400    memcpy ((char *)&floor_count, (char *)tower, twr_c_tower_flr_count_size);
401    RPC_RESOLVE_ENDIAN_INT16 (floor_count);
402
403    tower += twr_c_tower_flr_count_size;
404
405    /*
406     * Skip over the (application's) upper floors while we look for the
407     * beginning of the dnet-specific lower floors.
408     */
409    for (count = 0; count < floor_count; count++)
410    {
411        /*
412         * Get the length of this floor's protocol id field (don't
413         * advance the pointer).
414         */
415        memcpy ((char *)&id_size, (char *)tower,
416                TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
417        RPC_RESOLVE_ENDIAN_INT16 (id_size);
418
419        /*
420         * Get the protocol id (don't advance the pointer).
421         * Expect one byte; no need to convert.
422         */
423        memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE),
424                twr_c_tower_prot_id_size);
425
426        /*
427         * See if we support the protocol id.
428         */
429        if ( (id_size == twr_c_tower_prot_id_size) &&
430             (id ==  TWR_C_FLR_PROT_ID_DNA) )
431        {
432            /*
433             * Indicate we found the beginning of the dnet floors.
434             */
435            *status = twr_s_ok;
436
437            break;
438        }
439        else
440        {
441            /*
442             * Skip this floor.  Get the address size in order
443             * to know how much to skip.
444             */
445            memcpy ((char *)&addr_size,
446                    (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE +
447                            id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE);
448            RPC_RESOLVE_ENDIAN_INT16 (addr_size);
449
450            tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size +
451                     TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size;
452
453            /*
454             * For now, assume we don't find the floors we're looking for.
455             */
456            *status = twr_s_unknown_tower;
457        }
458    }
459
460    if (*status != twr_s_ok)
461    {
462        return;
463    }
464
465    /*
466     * Skip the floor's protocol id field length and protocol id
467     * (now move the pointer).  We already know it's TWR_C_FLR_PROT_ID_DNA.
468     */
469    tower += (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size);
470
471    /*
472     * Allocate space for a DECnet sockaddr
473     */
474    length = sizeof(struct sockaddr_dn);
475
476    RPC_MEM_ALLOC (
477                   *sa,
478                   sockaddr_p_t,
479                   length,
480                   RPC_C_MEM_SOCKADDR,
481                   RPC_C_MEM_WAITOK );
482
483    *sa_len = length;
484
485    /*
486     * make sure unused bytes are null
487     */
488    memset ((char *) *sa, 0, length);
489
490    /*
491     * define this as a DECnet family socket
492     */
493    ((struct sockaddr_dn *)(*sa))->sdn_family = RPC_C_NAF_ID_DNET;
494
495    /*
496     * Length of end user spec
497     */
498    memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE);
499    RPC_RESOLVE_ENDIAN_INT16 (addr_size);
500    tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE;
501
502    /*
503     * End user spec
504     */
505    memcpy (&((struct sockaddr_dn *)(*sa))->sdn_objnum,
506            (char *)tower,
507            addr_size);
508
509    tower += addr_size;
510
511    /*
512     * Length of host transport
513     */
514    memcpy ((char *)&id_size, (char *)tower,
515            TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
516    RPC_RESOLVE_ENDIAN_INT16 (id_size);
517    tower  += TWR_C_TOWER_FLR_LHS_COUNT_SIZE;
518
519    /*
520     * Transport id
521     * Expect one byte; no need to convert.
522     */
523    memcpy ((char *)&id, (char *)tower, twr_c_tower_prot_id_size);
524    tower += id_size;
525
526    if ((id_size != twr_c_tower_prot_id_size) ||
527        (id != TWR_C_FLR_PROT_ID_NSP))
528    {
529        *status = twr_s_unknown_tower;
530
531        RPC_MEM_FREE (*sa, RPC_C_MEM_SOCKADDR);
532
533        return;
534    }
535
536    /*
537     * Length of sdn_flags
538     */
539    memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE);
540    RPC_RESOLVE_ENDIAN_INT16 (addr_size);
541    tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE;
542
543    /*
544     * this field is probably null
545     */
546    if (addr_size)
547    {
548        memcpy ( &((struct sockaddr_dn *)(*sa))->sdn_flags,
549                (char *)tower,
550                addr_size);
551
552        tower += addr_size;
553    }
554
555    /*
556     * Length of routing id
557     */
558    memcpy ((char *)&id_size, (char *)tower,
559            TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
560    RPC_RESOLVE_ENDIAN_INT16 (id_size);
561    tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE;
562
563    /*
564     * Protocol id
565     * Expect one byte, so no need to convert.
566     */
567    memcpy ((char *)&id, (char *)tower, twr_c_tower_prot_id_size);
568    tower += id_size;
569
570    if ( (id_size != twr_c_tower_prot_id_size) ||
571         (id != TWR_C_FLR_PROT_ID_ROUTING) )
572    {
573        *status = twr_s_unknown_tower;
574
575        RPC_MEM_FREE (*sa, RPC_C_MEM_SOCKADDR);
576
577        return;
578    }
579
580    /*
581     * the length of host address
582     */
583    memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE);
584    RPC_RESOLVE_ENDIAN_INT16 (addr_size);
585    tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE;
586
587    memcpy (&((struct sockaddr_dn *)(*sa))->sdn_add,
588            (char *)tower,
589            addr_size);
590
591    *status = twr_s_ok;
592}
593#else
594static int _naf_dnet_dummy_ = 0 ;
595#endif /* NAF_DNET */
596