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_uxd.c
82**
83**  FACILITY:
84**
85**      Protocol Tower Services for the internet 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#include <com.h>        /* Common communications services */
101#include <twrp.h>	/* Private tower services */
102#include <uxdnaf.h>
103
104/*
105 *  Include the Internet specific socket address
106 */
107#include <sys/un.h>
108
109/*
110**++
111**
112**  ROUTINE NAME:       twr_uxd_lower_flrs_from_sa
113**
114**  SCOPE:              PUBLIC - declared in twr.idl
115**
116**  DESCRIPTION:
117**
118**  Creates the canonical representation of an internet protocol tower's
119**  lower floors from a sockaddr. The canonical form can be transmitted
120**  on the wire, or included in a DNS tower.
121**
122**  INPUTS:
123**
124**      trans_prot      Integer value specifying the transport layer
125**                      protocol for the Internet address family.
126**                      For address family RPC_C_NAF_ID_UXD specify:
127**
128**                         RPC_C_NETWORK_PROTOCOL_ID_UXD for udp
129**
130**      sa              Internet-specific socket address data
131**                      structure.
132**
133**  INPUTS/OUTPUTS:     none
134**
135**  OUTPUTS:
136**
137**      lower_flrs      Returns the lower tower floors in a twr_t
138**                      structure (includes the floor count in the
139**                      "tower_octet_string" member).
140**
141**      status          A value indicating the return status of the routine:
142**                          twr_s_ok
143**                          twr_s_unknown_sa
144**
145**  IMPLICIT INPUTS:    none
146**
147**  IMPLICIT OUTPUTS:   none
148**
149**  FUNCTION VALUE:     void
150**
151**  SIDE EFFECTS:       none
152**
153**--
154**/
155
156PUBLIC void twr_uxd_lower_flrs_from_sa
157(
158    sockaddr_p_t      sa,
159    twr_p_t           *lower_flrs,
160    unsigned32        *status
161)
162{
163    unsigned8   protocol_id[TWR_C_NUM_UXD_LOWER_FLRS];
164    unsigned16  id_size = TWR_C_TOWER_PROT_ID_SIZE,
165                floor_count,
166                related_data_size[TWR_C_NUM_UXD_LOWER_FLRS],
167                twr_rep_16;
168    unsigned32  count,
169                twr_t_length;
170    byte_p_t    related_data_ptr[TWR_C_NUM_UXD_LOWER_FLRS],
171                tmp_tower;
172    char       *sun_path;
173
174    CODING_ERROR (status);
175    RPC_VERIFY_INIT ();
176
177    if (sa->family == RPC_C_NAF_ID_UXD)
178    {
179        protocol_id[0] = TWR_C_FLR_PROT_ID_UXD;
180    }
181    else
182    {
183        *status = twr_s_unknown_sa;
184        return;
185    }
186
187    /*
188     * Since we now know the socket address we're dealing with,
189     * collect the sizes of each field to allocate memory, and
190     * remember the pointers to the fields so we can copy the
191     * data once we have allocated the tower string.
192     */
193    floor_count = TWR_C_NUM_UXD_LOWER_FLRS;
194
195    /*
196     * Not sure whether we need to "canonicalize" this.
197     */
198    sun_path = ((struct sockaddr_un *)sa)->sun_path;
199    if (strncmp(sun_path, RPC_C_UXD_DIR, RPC_C_UXD_DIR_LEN) == 0)
200    {
201        related_data_ptr[0] = (byte_p_t)&sun_path[RPC_C_UXD_DIR_LEN + 1];
202    }
203    else
204    {
205        related_data_ptr[0] = (byte_p_t)sun_path;
206    }
207    related_data_size[0] = strlen((char*) related_data_ptr[0]) + 1;
208
209    /*
210     * Calculate the length of the tower floors.
211     */
212
213    twr_t_length = TWR_C_TOWER_FLR_COUNT_SIZE;  /* to store floor count */
214
215    for ( count = 0; count < floor_count; count++ )
216    {
217        twr_t_length += TWR_C_FLR_OVERHEAD;
218        twr_t_length += related_data_size[count];
219    }
220
221    /*
222     * Next allocate space for the tower structure
223     */
224    RPC_MEM_ALLOC (
225        *lower_flrs,
226        twr_p_t,
227        sizeof (twr_t) + (twr_t_length - 1),
228        RPC_C_MEM_TOWER,
229        RPC_C_MEM_WAITOK );
230
231    /*
232     * Copy the length of the tower octet string into the tower structure
233     */
234    (*lower_flrs)->tower_length = twr_t_length;
235
236    /*
237     * Copy the floor information into the tower octet string
238     */
239
240    /*
241     * Use a temporary for the octet string since we need
242     * to increment the pointer.
243     */
244    tmp_tower = (*lower_flrs)->tower_octet_string;
245
246    /*
247     * Copy the number of floors into the tower octet string
248     */
249    twr_rep_16 = floor_count;
250    RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16);
251    memcpy ((char *)tmp_tower, (char *)&twr_rep_16,
252            TWR_C_TOWER_FLR_COUNT_SIZE);
253
254    tmp_tower += TWR_C_TOWER_FLR_COUNT_SIZE;
255
256    /*
257     * Convert the protocol identifier size to its proper
258     * representation for use in the following loop.
259     */
260    RPC_RESOLVE_ENDIAN_INT16 (id_size);
261
262    for ( count = 0; count < floor_count; count++ )
263    {
264        /*
265         * Copy the length of the protocol identifier field into
266         * tower octet string.  (Converted before the loop.)
267         */
268        memcpy ((char *)tmp_tower, (char *)&id_size,
269                TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
270
271        tmp_tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE;
272
273        /*
274         * Copy the protocol identifier into tower octet string
275         * (1 byte so no need to convert endian representation).
276         */
277        memcpy ((char *)tmp_tower, (char *)&(protocol_id[count]),
278                TWR_C_TOWER_PROT_ID_SIZE);
279
280        tmp_tower += TWR_C_TOWER_PROT_ID_SIZE;
281
282        /*
283         * Copy the length of the address data field into
284         * tower octet string.
285         */
286        twr_rep_16 = related_data_size[count];
287        RPC_RESOLVE_ENDIAN_INT16 (twr_rep_16);
288        memcpy ((char *)tmp_tower, (char *)&twr_rep_16,
289                TWR_C_TOWER_FLR_RHS_COUNT_SIZE);
290
291        tmp_tower += TWR_C_TOWER_FLR_RHS_COUNT_SIZE;
292
293        /*
294         * If there is addressing data, copy the address data field into
295         * tower octet string
296         */
297        if (related_data_size[count])
298        {
299            memcpy ((char *)tmp_tower, (char *)related_data_ptr[count],
300                    related_data_size[count]);
301
302            /*
303             * Set up for the next floor.
304             */
305            tmp_tower += related_data_size[count];
306        }
307    }
308
309    *status = twr_s_ok;
310}
311
312/*
313**++
314**
315**  ROUTINE NAME:       twr_uxd_lower_flrs_to_sa
316**
317**  SCOPE:              PUBLIC - declared in twr.idl
318**
319**  DESCRIPTION:
320**
321**  Creates an internet sockaddr from the canonical representation of an
322**  internet protocol tower's lower floors.
323**
324**  INPUTS:
325**
326**      tower_octet_string
327**                      The protocol tower to convert to a sockaddr.
328**
329**  INPUTS/OUTPUTS:     none
330**
331**  OUTPUTS:
332**
333**      sa            Returns a pointer to the created sockaddr structure.
334**
335**      sa_len          Returns the length, in bytes, of the returned
336**                      "sa" argument.
337**
338**      status          A value indicating the return status of the routine:
339**                          twr_s_ok
340**                          twr_s_unknown_tower
341**
342**  IMPLICIT INPUTS:    none
343**
344**  IMPLICIT OUTPUTS:   none
345**
346**  FUNCTION VALUE:     void
347**
348**  SIDE EFFECTS:       none
349**
350**--
351**/
352
353PUBLIC void twr_uxd_lower_flrs_to_sa
354(
355    byte_p_t          tower_octet_string,
356    sockaddr_p_t      *sa,
357    unsigned32        *sa_len,
358    unsigned32        *status
359)
360{
361    unsigned8   id;
362    byte_p_t    tower;
363    unsigned16  count,
364                floor_count,
365                id_size,
366                addr_size;
367    unsigned32  length;
368
369    CODING_ERROR (status);
370    RPC_VERIFY_INIT ();
371
372    id_size = 0;
373
374    /*
375     * Make sure we have a pointer to some data structure.
376     */
377    if ( !(tower = tower_octet_string))
378    {
379        *status = twr_s_unknown_tower;
380        return;
381    }
382
383    /*
384     * Get the tower floor count
385     */
386    memcpy ((char *)&floor_count, (char *)tower, TWR_C_TOWER_FLR_COUNT_SIZE);
387    RPC_RESOLVE_ENDIAN_INT16 (floor_count);
388
389    tower += TWR_C_TOWER_FLR_COUNT_SIZE;
390
391    /*
392     * Skip over the (application's) upper floors while we look for the
393     * beginning of the uxd-specific lower floors.
394     */
395    for ( count = 0; count < floor_count; count++ )
396    {
397        /*
398         * Get the length of this floor's protocol id field (don't advance
399         * the pointer).
400         */
401        memcpy ((char *)&id_size, (char *)tower,
402                TWR_C_TOWER_FLR_LHS_COUNT_SIZE);
403        RPC_RESOLVE_ENDIAN_INT16 (id_size);
404
405        /*
406         * Get the protocol id (don't advance the pointer).
407         * Expect one byte; no need to convert.
408         */
409        memcpy ((char *)&id, (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE),
410                TWR_C_TOWER_PROT_ID_SIZE);
411
412        /*
413         * See if we support the protocol id.
414         */
415        if ( (id_size == TWR_C_TOWER_PROT_ID_SIZE) &&
416             (id == TWR_C_FLR_PROT_ID_UXD))
417        {
418            /*
419             * Indicate we found the beginning of the uxd floors.
420             */
421            *status = twr_s_ok;
422
423            break;
424        }
425        else
426        {
427            /*
428             * Skip this floor.  Get the address size in order
429             * to know how much to skip.
430             */
431            memcpy ((char *)&addr_size,
432                    (char *)(tower + TWR_C_TOWER_FLR_LHS_COUNT_SIZE +
433                            id_size), TWR_C_TOWER_FLR_RHS_COUNT_SIZE);
434            RPC_RESOLVE_ENDIAN_INT16 (addr_size);
435
436            tower += TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size +
437                     TWR_C_TOWER_FLR_RHS_COUNT_SIZE + addr_size;
438
439            /*
440             * For now, assume we don't find the floors we're looking for.
441             */
442            *status = twr_s_unknown_tower;
443        }
444    }
445
446    if (*status != twr_s_ok)
447    {
448        return;
449    }
450
451    /*
452     * Skip the floor's protocol id field length and protocol id
453     * (now move the pointer).  We already know it's
454     * TWR_C_FLR_PROT_ID_UXD.
455     */
456    tower += (TWR_C_TOWER_FLR_LHS_COUNT_SIZE + id_size);
457
458    /*
459     * Allocate space for sockaddr
460     */
461    length = sizeof(struct sockaddr_un);
462
463    RPC_MEM_ALLOC (
464        *sa,
465        sockaddr_p_t,
466        length,
467        RPC_C_MEM_SOCKADDR,
468        RPC_C_MEM_WAITOK );
469
470    *sa_len = length;
471
472    /*
473     * make sure unused bytes are null
474     */
475    memset ((char *) *sa, 0, length);
476
477    /*
478     * define this as an internet family socket
479     */
480    ((struct sockaddr_un *)(*sa))->sun_family = RPC_C_NAF_ID_UXD;
481
482    /*
483     * Get the length of endpoint address
484     */
485    memcpy ((char *)&addr_size, (char *)tower, RPC_C_TOWER_FLR_RHS_COUNT_SIZE);
486    RPC_RESOLVE_ENDIAN_INT16 (addr_size);
487    tower += RPC_C_TOWER_FLR_RHS_COUNT_SIZE;
488
489    /*
490     * Copy the endpoint address to the sockaddr.
491     */
492    tower[addr_size - 1] = '\0';
493    if (tower[0] != '/')
494    {
495        addr_size += RPC_C_UXD_DIR_LEN + 1;
496    }
497    if (addr_size > sizeof(((struct sockaddr_un *)(*sa))->sun_path))
498    {
499        *status = rpc_s_no_memory;
500        RPC_MEM_FREE (*sa, RPC_C_MEM_SOCKADDR);
501        *sa = NULL;
502        return;
503    }
504
505    snprintf(((struct sockaddr_un *)(*sa))->sun_path,
506             sizeof(((struct sockaddr_un *)(*sa))->sun_path),
507             "%s%s", (tower[0] == '/') ? "" : RPC_C_UXD_DIR"/",
508             tower);
509
510    *status = twr_s_ok;
511}
512