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**      ipnaf.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  This module contains routines specific to the Internet Protocol
90**  and the Internet Network Address Family extension service.
91**  An initialization routine is provided to be called at RPC
92**  initialization time provided, the Internet Protocol is supported
93**  on the local host platform.  The remaining routines are entered
94**  through an Entry Point Vector specific to the Internet Protocol.
95**
96**
97*/
98
99#include <commonp.h>
100#include <com.h>
101#include <comnaf.h>
102#include <ipnaf.h>
103#include <comsoc_bsd.h>
104
105#undef __USE_GNU
106
107#ifndef DO_NOT_ALLOW_HOSTNAMES
108#  include <netdb.h>
109#endif
110
111
112/***********************************************************************
113 *
114 *  Macros for sprint/scanf substitutes.
115 */
116
117#ifndef NO_SSCANF
118#  define RPC__IP_ENDPOINT_SSCANF   sscanf
119#else
120#  define RPC__IP_ENDPOINT_SSCANF   rpc__ip_endpoint_sscanf
121#endif
122
123#ifndef NO_SPRINTF
124#  define RPC__IP_ENDPOINT_SPRINTF  sprintf
125#  define RPC__IP_NETWORK_SPRINTF   sprintf
126#else
127#  define RPC__IP_ENDPOINT_SPRINTF  rpc__ip_endpoint_sprintf
128#  define RPC__IP_NETWORK_SPRINTF   rpc__ip_network_sprintf
129#endif
130
131
132/***********************************************************************
133 *
134 *  Routine Prototypes for the Internet Extension service routines.
135 */
136
137INTERNAL void addr_alloc (
138        rpc_protseq_id_t             /*rpc_protseq_id*/,
139        rpc_naf_id_t                 /*naf_id*/,
140        unsigned_char_p_t            /*endpoint*/,
141        unsigned_char_p_t            /*netaddr*/,
142        unsigned_char_p_t            /*network_options*/,
143        rpc_addr_p_t                * /*rpc_addr*/,
144        unsigned32                  * /*status*/
145    );
146
147INTERNAL void addr_copy (
148        rpc_addr_p_t                 /*srpc_addr*/,
149        rpc_addr_p_t                * /*drpc_addr*/,
150        unsigned32                  * /*status*/
151    );
152
153INTERNAL void addr_free (
154        rpc_addr_p_t                * /*rpc_addr*/,
155        unsigned32                  * /*status*/
156    );
157
158INTERNAL void addr_set_endpoint (
159        unsigned_char_p_t            /*endpoint*/,
160        rpc_addr_p_t                * /*rpc_addr*/,
161        unsigned32                  * /*status*/
162    );
163
164INTERNAL void addr_inq_endpoint (
165        rpc_addr_p_t                 /*rpc_addr*/,
166        unsigned_char_t             ** /*endpoint*/,
167        unsigned32                  * /*status*/
168    );
169
170INTERNAL void addr_set_netaddr (
171        unsigned_char_p_t            /*netaddr*/,
172        rpc_addr_p_t                * /*rpc_addr*/,
173        unsigned32                  * /*status*/
174    );
175
176INTERNAL void addr_inq_netaddr (
177        rpc_addr_p_t                 /*rpc_addr*/,
178        unsigned_char_t             ** /*netaddr*/,
179        unsigned32                  * /*status*/
180    );
181
182INTERNAL void addr_set_options (
183        unsigned_char_p_t            /*network_options*/,
184        rpc_addr_p_t                * /*rpc_addr*/,
185        unsigned32                  * /*status*/
186    );
187
188INTERNAL void addr_inq_options (
189        rpc_addr_p_t                 /*rpc_addr*/,
190        unsigned_char_t             ** /*network_options*/,
191        unsigned32                  * /*status*/
192    );
193
194INTERNAL void desc_inq_network (
195        rpc_socket_t                 /*desc*/,
196        rpc_network_if_id_t         * /*socket_type*/,
197        rpc_network_protocol_id_t   * /*protocol_id*/,
198        unsigned32                  * /*status*/
199    );
200
201INTERNAL void inq_max_tsdu (
202        rpc_naf_id_t                 /*naf_id*/,
203        rpc_network_if_id_t          /*iftype*/,
204        rpc_network_protocol_id_t    /*protocol*/,
205        unsigned32                  * /*max_tsdu*/,
206        unsigned32                  * /*status*/
207    );
208
209INTERNAL boolean addr_compare (
210        rpc_addr_p_t                 /*addr1*/,
211        rpc_addr_p_t                 /*addr2*/,
212        unsigned32                  * /*status*/
213    );
214
215INTERNAL void inq_max_pth_unfrag_tpdu (
216        rpc_addr_p_t                 /*rpc_addr*/,
217        rpc_network_if_id_t          /*iftype*/,
218        rpc_network_protocol_id_t    /*protocol*/,
219        unsigned32                  * /*max_tpdu*/,
220        unsigned32                  * /*status*/
221    );
222
223INTERNAL void inq_max_loc_unfrag_tpdu (
224        rpc_naf_id_t                 /*naf_id*/,
225        rpc_network_if_id_t          /*iftype*/,
226        rpc_network_protocol_id_t    /*protocol*/,
227        unsigned32                  * /*max_tpdu*/,
228        unsigned32                  * /*status*/
229    );
230
231INTERNAL void set_pkt_nodelay (
232        rpc_socket_t                 /*desc*/,
233        unsigned32                  * /*status*/
234    );
235
236INTERNAL boolean is_connect_closed (
237        rpc_socket_t                 /*desc*/,
238        unsigned32                  * /*status*/
239    );
240
241INTERNAL void tower_flrs_from_addr (
242        rpc_addr_p_t                 /*rpc_addr*/,
243        twr_p_t                     * /*lower_flrs*/,
244        unsigned32                  * /*status*/
245    );
246
247INTERNAL void tower_flrs_to_addr (
248        byte_p_t                     /*tower_octet_string*/,
249        rpc_addr_p_t                * /*rpc_addr*/,
250        unsigned32                  * /*status*/
251    );
252
253INTERNAL void desc_inq_peer_addr (
254        rpc_protseq_id_t             /*protseq_id*/,
255        rpc_socket_t                 /*desc*/,
256        rpc_addr_p_t                * /*rpc_addr*/,
257        unsigned32                  * /*status*/
258    );
259
260INTERNAL void set_port_restriction (
261        rpc_protseq_id_t             /*protseq_id*/,
262        unsigned32                   /*n_elements*/,
263        unsigned_char_p_t           * /*first_port_name_list*/,
264        unsigned_char_p_t           * /*last_port_name_list*/,
265        unsigned32                  * /*status*/
266    );
267
268INTERNAL void get_next_restricted_port (
269        rpc_protseq_id_t             /*protseq_id*/,
270        unsigned_char_p_t           * /*port_name*/,
271        unsigned32                  * /*status*/
272    );
273
274INTERNAL void inq_max_frag_size (
275        rpc_addr_p_t                 /*rpc_addr*/,
276        unsigned32                  * /*max_frag_size*/,
277        unsigned32                  * /*status*/
278    );
279
280
281/*
282**++
283**
284**  ROUTINE NAME:       rpc__ip_init
285**
286**  SCOPE:              PRIVATE - EPV declared in ipnaf.h
287**
288**  DESCRIPTION:
289**
290**  Internet Address Family Initialization routine, rpc__ip_init, is
291**  calld only once, by the Communications Service initialization
292**  procedure,  at the time RPC is initialized.  If the Communications
293**  Service initialization determines that the Internet protocol
294**  family is supported on the local host platform it will call this
295**  initialization routine.  It is responsible for all Internet
296**  specific initialization for the current RPC.  It will place in
297**  Network Address Family Table, a pointer to the Internet family Entry
298**  Point Vector.  Afterward all calls to the IP extension service
299**  routines will be vectored through this EPV.
300**
301**  INPUTS:             none
302**
303**  INPUTS/OUTPUTS:
304**
305**      naf_epv         The address of a pointer in the Network Address Family
306**                      Table whre the pointer to the Entry Point Vectorto
307**                      the IP service routines is inserted by this routine.
308**
309**  OUTPUTS:
310**
311**      status          A value indicating the status of the routine.
312**
313**          rpc_s_ok        The call was successful.
314**
315**          Any of the RPC Protocol Service status codes.
316**
317**  IMPLICIT INPUTS:    none
318**
319**  IMPLICIT OUTPUTS:   none
320**
321**  FUNCTION VALUE:     none
322**
323**  SIDE EFFECTS:       none
324**
325**--
326**/
327
328#include <comp.h>
329PRIVATE void rpc__ip_naf_init_func(void)
330{
331	static rpc_naf_id_elt_t naf[1] = {
332		{
333			rpc__ip_init,
334			RPC_C_NAF_ID_IP,
335			RPC_C_NETWORK_IF_ID_DGRAM,
336			NULL
337		}
338	};
339	static rpc_tower_prot_ids_t prot_ids[2] = {
340		{ rpc_c_protseq_id_ncadg_ip_udp,   3,
341			{ {0x0A,   { 0, 0, 0, 0, 0, {0} }},       /* DG */
342				{0x08,   { 0, 0, 0, 0, 0, {0} }}, /* port */
343				{0x09,   { 0, 0, 0, 0, 0, {0} }}, /* IP addr */
344				{0x00,   { 0, 0, 0, 0, 0, {0} }}
345			}
346		},
347
348		{ rpc_c_protseq_id_ncacn_ip_tcp,   3,
349			{ {0x0B,   { 0, 0, 0, 0, 0, {0} }},       /* CN */
350				{0x07,   { 0, 0, 0, 0, 0, {0} }}, /* port */
351				{0x09,   { 0, 0, 0, 0, 0, {0} }}, /* IP addr */
352				{0x00,   { 0, 0, 0, 0, 0, {0} }}
353			}
354		}
355	};
356	static rpc_protseq_id_elt_t seq_ids[2] = {
357    {                                   /* Connection-RPC / IP / TCP */
358        0,
359        1, /* Uses endpoint mapper */
360        rpc_c_protseq_id_ncacn_ip_tcp,
361        RPC_C_PROTOCOL_ID_NCACN,
362        RPC_C_NAF_ID_IP,
363        RPC_C_NETWORK_PROTOCOL_ID_TCP,
364        RPC_C_NETWORK_IF_ID_STREAM,
365        RPC_PROTSEQ_NCACN_IP_TCP,
366        (rpc_port_restriction_list_p_t) NULL,
367        &rpc_g_bsd_socket_vtbl
368    },
369    {                                   /* Datagram-RPC / IP / UDP */
370        0,
371        1, /* Uses endpoint mapper */
372        rpc_c_protseq_id_ncadg_ip_udp,
373        RPC_C_PROTOCOL_ID_NCADG,
374        RPC_C_NAF_ID_IP,
375        RPC_C_NETWORK_PROTOCOL_ID_UDP,
376        RPC_C_NETWORK_IF_ID_DGRAM,
377        RPC_PROTSEQ_NCADG_IP_UDP,
378        (rpc_port_restriction_list_p_t) NULL,
379        &rpc_g_bsd_socket_vtbl
380    }
381
382	};
383	rpc__register_protseq(seq_ids, 2);
384	rpc__register_tower_prot_id(prot_ids, 2);
385	rpc__register_naf_id(naf, 1);
386}
387
388PRIVATE void  rpc__ip_init
389(
390    rpc_naf_epv_p_t         *naf_epv,
391    unsigned32              *status
392)
393{
394    /*
395     * The Internal Entry Point Vectors for the Internet Protocol Family
396     * Extension service routines.  At RPC startup time, the IP init routine,
397     * rpc__ip_init, is responsible for inserting  a pointer to this EPV into
398     * the  Network Address Family Table.  Afterward,  all calls to the IP
399     * Extension  Service are vectored through these  EPVs.
400     */
401
402    static const rpc_naf_epv_t rpc_ip_epv =
403    {
404        .naf_addr_alloc =               addr_alloc,
405        .naf_addr_copy =                addr_copy,
406        .naf_addr_free =                addr_free,
407        .naf_addr_set_endpoint =        addr_set_endpoint,
408        .naf_addr_inq_endpoint =        addr_inq_endpoint,
409        .naf_addr_set_netaddr =         addr_set_netaddr,
410        .naf_addr_inq_netaddr =         addr_inq_netaddr,
411        .naf_addr_set_options =         addr_set_options,
412        .naf_addr_inq_options =         addr_inq_options,
413        .naf_desc_inq_addr =            rpc__ip_desc_inq_addr,
414        .naf_desc_inq_network =         desc_inq_network,
415        .naf_inq_max_tsdu =             inq_max_tsdu,
416        .naf_get_broadcast =            rpc__ip_get_broadcast,
417        .naf_addr_compare =             addr_compare,
418        .naf_inq_max_pth_unfrg_tpdu =   inq_max_pth_unfrag_tpdu,
419        .naf_inq_max_loc_unfrg_tpdu =   inq_max_loc_unfrag_tpdu,
420        .naf_set_pkt_nodelay =          set_pkt_nodelay,
421        .naf_is_connect_closed =        is_connect_closed,
422        .naf_tower_flrs_from_addr =     tower_flrs_from_addr,
423        .naf_tower_flrs_to_addr =       tower_flrs_to_addr,
424        .naf_desc_inq_peer_addr =       desc_inq_peer_addr,
425        .naf_set_port_restriction =     set_port_restriction,
426        .naf_get_next_restricted_port = get_next_restricted_port,
427        .naf_inq_max_frag_size =        inq_max_frag_size
428    };
429    unsigned32 lstatus;
430
431    rpc__ip_init_local_addr_vec (&lstatus);
432
433    /*
434     * place the address of EPV into Network Address Family Table
435     */
436    *naf_epv = &rpc_ip_epv;
437
438    *status = rpc_s_ok;
439}
440
441/*
442**++
443**
444**  ROUTINE NAME:       addr_alloc
445**
446**  SCOPE:              INTERNAL - declared locally
447**
448**  DESCRIPTION:
449**
450**  Create a copy of an RPC address. Allocate memory for a variable
451**  length RPC address, for the IP service.  Insert the Internet
452**  address and endpoint along with the overall length of the allocated
453**  memory, together with any additional parameters required by the IP
454**  service.
455**
456**  INPUTS:
457**
458**      rpc_protseq_id  Protocol Sequence ID representing an IP Network
459**                      Address Family, its Transport Protocol, and type.
460**
461**      naf_id          Network Address Family ID serves as index into
462**                      EPV for IP routines.
463**
464**      endpoint        String containing endpoint to insert into newly
465**                      allocated RPC address.
466**
467**      netaddr         String containing Internet format network
468**                      address to be inserted in RPC addr.
469**
470**      network_options String containing options to be placed in
471**                      RPC address.  - Not used by IP service.
472**
473**  INPUTS/OUTPUTS:
474**
475**      rpc_addr        The address of a pointer to an RPC address -
476**                      returned with the address of the memory
477**                      allocated by this routine.
478**
479**  OUTPUTS:
480**
481**      status          A value indicating the status of the routine.
482**
483**          rpc_s_ok           The call was successful.
484**
485**          rpc_s_no_memory     Call to malloc failed to allocate memory
486**
487**          Any of the RPC Protocol Service status codes.
488**
489**  IMPLICIT INPUTS:    none
490**
491**  IMPLICIT OUTPUTS:   none
492**
493**  FUNCTION VALUE:     none
494**
495**  SIDE EFFECTS:       none
496**
497**
498**--
499**/
500
501INTERNAL void addr_alloc
502(
503    rpc_protseq_id_t        rpc_protseq_id,
504    rpc_naf_id_t            naf_id,
505    unsigned_char_p_t       endpoint,
506    unsigned_char_p_t       netaddr,
507    unsigned_char_p_t       network_options ATTRIBUTE_UNUSED,
508    rpc_addr_p_t            *rpc_addr,
509    unsigned32              *status
510)
511{
512    CODING_ERROR (status);
513
514    /*
515     * allocate memory for the new RPC address
516     */
517
518    RPC_MEM_ALLOC (
519        *rpc_addr,
520        rpc_addr_p_t,
521        sizeof (rpc_ip_addr_t),
522        RPC_C_MEM_RPC_ADDR,
523        RPC_C_MEM_WAITOK);
524
525    if (*rpc_addr == NULL)
526    {
527        *status = rpc_s_no_memory;
528        return;
529    }
530
531    /*
532     * zero allocated memory
533     */
534    /* b_z_e_r_o ((unsigned8 *) *rpc_addr, sizeof (rpc_ip_addr_t));*/
535
536    memset( *rpc_addr, 0, sizeof (rpc_ip_addr_t));
537
538    /*
539     * insert id, length, family into rpc address
540     */
541    (*rpc_addr)->rpc_protseq_id = rpc_protseq_id;
542    (*rpc_addr)->len = sizeof (struct sockaddr_in);
543    (*rpc_addr)->sa.family = naf_id;
544
545    /*
546     * set the endpoint in the RPC addr
547     */
548    addr_set_endpoint (endpoint, rpc_addr, status);
549    if (*status != rpc_s_ok) return;
550
551    /*
552     * set the network address in the RPC addr
553     */
554    addr_set_netaddr (netaddr, rpc_addr, status);
555    if (*status != rpc_s_ok) return;
556
557    *status = rpc_s_ok;
558}
559
560/*
561**++
562**
563**  ROUTINE NAME:       addr_copy
564**
565**  SCOPE:              INTERNAL - declared locally
566**
567**  DESCRIPTION:
568**
569**  Obtain the length from the source RPC address.  Allocate memory for a
570**  new, destination  RPC address. Do a byte copy from the surce address
571**  to the destination address.
572**
573**  INPUTS:
574**
575**     src_rpc_addr     The address of a pointer to an RPC address to be
576**                      copied.  It must be the correct format for Internet
577**                      Protocol.
578**
579**  INPUTS/OUTPUTS:
580**
581**     dst_rpc_addr     The address of a pointer to an RPC address -returned
582**                      with the address of the memory allocated by
583**                      this routine.
584**
585**  OUTPUTS:
586**
587**      status          A value indicating the status of the routine.
588**
589**      rpc_s_ok            The call was successful.
590**
591**      rpc_s_no_memory     Call to malloc failed to allocate memory
592**
593**      rpc_s_invalid_naf_id  Source RPC address appeared invalid
594**
595**
596**  IMPLICIT INPUTS:
597**
598**        A check is performed on the source RPC address before malloc.  It
599**        must be the IP family.
600**
601**  IMPLICIT OUTPUTS:   none
602**
603**  FUNCTION VALUE:     none
604**
605**  SIDE EFFECTS:
606**
607**           In the event, the addres of a of memory segment contained in
608**           rpc_addr, is not valid or the length isn't as long as is
609**           indicated, a memory fault may result.
610**
611**--
612**/
613
614INTERNAL void addr_copy
615(
616    rpc_addr_p_t            src_rpc_addr,
617    rpc_addr_p_t            *dst_rpc_addr,
618    unsigned32              *status
619)
620{
621    CODING_ERROR (status);
622
623    /*
624     * if the source RPC address looks valid - IP family ok
625     */
626    if (src_rpc_addr->sa.family == RPC_C_NAF_ID_IP)
627    {
628        /*
629         * allocate memory for the new RPC address
630         */
631        RPC_MEM_ALLOC (
632            *dst_rpc_addr,
633            rpc_addr_p_t,
634            sizeof (rpc_ip_addr_t),
635            RPC_C_MEM_RPC_ADDR,
636            RPC_C_MEM_WAITOK);
637
638        if (*dst_rpc_addr == NULL)
639        {
640            *status = rpc_s_no_memory;
641            return;
642        }
643
644        /*
645         * Copy source rpc address to destination rpc address
646         */
647        /* b_c_o_p_y ((unsigned8 *) src_rpc_addr, (unsigned8 *) *dst_rpc_addr,
648                sizeof (rpc_ip_addr_t));*/
649
650        memmove( *dst_rpc_addr, src_rpc_addr, sizeof (rpc_ip_addr_t));
651
652        *status = rpc_s_ok;
653        return;
654    }
655
656    *status = rpc_s_invalid_naf_id;
657}
658
659/*
660**++
661**
662**  ROUTINE NAME:       addr_free
663**
664**  SCOPE:              INTERNAL - declared locally
665**
666**  DESCRIPTION:
667**
668**  Free the memory for the RPC address pointed to by the argument
669**  address pointer rpc_addr.  Null the address pointer.  The memory
670**  must have been previously allocated by RPC_MEM_ALLC.
671**
672**  INPUTS:             none
673**
674**  INPUTS/OUTPUTS:
675**
676**     rpc_addr         The address of a pointer to an RPC address -returned
677**                      with a NULL value.
678**
679**  OUTPUTS:
680**
681**      status          A value indicating the status of the routine.
682**
683**          rpc_s_ok        The call was successful.
684**
685**
686**  IMPLICIT INPUTS:    none
687**
688**  IMPLICIT OUTPUTS:   none
689**
690**  FUNCTION VALUE:     none
691**
692**  SIDE EFFECTS:
693**           In the event, the segment of memory refered to by pointer
694**           rpc_addr, is allocated by means other than RPC_MEM_ALLOC,
695**           unpredictable results will occur when this routine is called.
696**--
697**/
698
699INTERNAL void addr_free
700(
701    rpc_addr_p_t            *rpc_addr,
702    unsigned32              *status
703)
704{
705    CODING_ERROR (status);
706
707    /*
708     * free memory of RPC addr
709     */
710    RPC_MEM_FREE (*rpc_addr, RPC_C_MEM_RPC_ADDR);
711
712    /*
713     * indicate that the rpc_addr is now empty
714     */
715    *rpc_addr = NULL;
716
717    *status = rpc_s_ok;
718}
719
720/*
721**++
722**
723**  ROUTINE NAME:       addr_set_endpoint
724**
725**  SCOPE:              INTERNAL - declared locally
726**
727**  DESCRIPTION:
728**
729**    Receive the null terminated ascii character string,  rpc_endpoint
730**    and convert to the Internet Protocol byte order format.  Insert
731**    into the RPC address, pointed to by argument rpc_addr.  The only
732**    acceptible endpoint for IP is numeric asci string, or a NULL string.
733**
734**  INPUTS:
735**
736**      endpoint        String containing endpoint to insert into RPC address.
737**                      For IP must contain an ASCII numeric value, or NULL.
738**
739**  INPUTS/OUTPUTS:
740**
741**      rpc_addr        The address of a pointer to an RPC address where
742**                      the endpoint is to be inserted.
743**
744**  OUTPUTS:
745**
746**      status          A value indicating the status of the routine.
747**
748**          rpc_s_ok                 The call was successful.
749**
750**          rpc_s_invalid_naf_id  Argument, endpoint contains an
751**                                  unauthorized pointer value.
752**          rpc_s_invalid_endpoint_format Endpoint Argument can not be
753**                                  converted (not numeric).
754**
755**  IMPLICIT INPUTS:
756**
757**      A NULL, (first byte NULL), endpoint string is an indicator to
758**      the routine to delete the endpoint from the RPC address. indicated.
759**
760**  IMPLICIT OUTPUTS:   none
761**
762**  FUNCTION VALUE:     none
763**
764**  SIDE EFFECTS:       none
765**
766**--
767**/
768
769INTERNAL void addr_set_endpoint
770(
771    unsigned_char_p_t       endpoint,
772    rpc_addr_p_t            *rpc_addr,
773    unsigned32              *status
774)
775{
776    rpc_ip_addr_p_t     ip_addr = (rpc_ip_addr_p_t) *rpc_addr;
777    int                 ep;
778    int                 ret;
779
780    CODING_ERROR (status);
781
782    /*
783     * check to see if this is a request to remove the endpoint
784     */
785    if (endpoint == NULL || strlen ((char *) endpoint) == 0)
786    {
787        ip_addr->sa.sin_port = 0;
788        *status = rpc_s_ok;
789        return;
790    }
791
792    if ((strspn ((char *)endpoint, "0123456789"))
793         != (strlen ((char *)endpoint)))
794    {
795        *status = rpc_s_invalid_endpoint_format;
796        return;
797    }
798
799    /*
800     * convert the endpoint string to network format
801     * and insert in RPC address
802     */
803
804    ret = RPC__IP_ENDPOINT_SSCANF((char *) endpoint, "%d", &ep);
805    if (ret != 1)
806    {
807        *status = rpc_s_invalid_endpoint_format;
808        return;
809    }
810
811    ip_addr->sa.sin_port = htons (ep);
812
813    *status = rpc_s_ok;
814}
815
816/*
817**++
818**
819**  ROUTINE NAME:       addr_inq_endpoint
820**
821**  SCOPE:              INTERNAL - declared locally
822**
823**  DESCRIPTION:
824**
825**    From the RPC address indicated by arg., rpc_addr, examine the
826**    endpoint.  Convert the endopint value to a NULL terminated asci
827**    character string to be returned in the memory segment pointed to
828**    by arg., endpoint.
829**
830**  INPUTS:
831**
832**      rpc_addr        The address of a pointer to an RPC address that
833**                      to be inspected.
834**
835**  INPUTS/OUTPUTS:     none
836**
837**
838**  OUTPUTS:
839**
840**      endpoint        String pointer indicating where the endpoint
841**                      string is to be placed.
842**
843**      status          A value indicating the status of the routine.
844**
845**          rpc_s_ok           The call was successful.
846**
847**          Any of the RPC Protocol Service status codes.
848**
849**  IMPLICIT INPUTS:    none
850**
851**  IMPLICIT OUTPUTS:
852**
853**      A zero length string will be returned if the RPC address contains
854**      no endpoint.
855**
856**  FUNCTION VALUE:     none
857**
858**  SIDE EFFECTS:
859**
860**    CAUTION -- since this routine has no way of knowing the exact
861**      length of the endpoint string which will be derived.  It
862**      is asumed that the caller has provided, rpc_c_endpoint_max
863**      (or at least "enough") space for the endpoint string.
864**--
865**/
866
867INTERNAL void addr_inq_endpoint
868(
869    rpc_addr_p_t            rpc_addr,
870    unsigned_char_t         **endpoint,
871    unsigned32              *status
872)
873{
874#define     RPC_C_ENDPOINT_IP_MAX   6   /* 5 ascii digits + nul */
875    rpc_ip_addr_p_t     ip_addr = (rpc_ip_addr_p_t) rpc_addr;
876    unsigned16          ep;
877
878    CODING_ERROR (status);
879
880    /*
881     * convert endpoint to local platform byte order format
882     */
883    ep = ntohs (ip_addr->sa.sin_port);
884
885    /*
886     * if no endpoint present, return null string. Otherwise,
887     * return the endpoint in Internet "dot" notation.
888     */
889    if (ep  ==  0)
890    {
891        RPC_MEM_ALLOC(
892            *endpoint,
893            unsigned_char_p_t,
894            sizeof(unsigned32),     /* can't stand to get just 1 byte */
895            RPC_C_MEM_STRING,
896            RPC_C_MEM_WAITOK);
897        *endpoint[0] = 0;
898    }
899    else
900    {
901        RPC_MEM_ALLOC(
902            *endpoint,
903            unsigned_char_p_t,
904            RPC_C_ENDPOINT_IP_MAX,
905            RPC_C_MEM_STRING,
906            RPC_C_MEM_WAITOK);
907        RPC__IP_ENDPOINT_SPRINTF((char *) *endpoint, "%u", ep);
908    }
909
910    *status = rpc_s_ok;
911}
912
913/*
914**++
915**
916**  ROUTINE NAME:       addr_set_netaddr
917**
918**  SCOPE:              INTERNAL - declared locally
919**
920**  DESCRIPTION:
921**
922**    Receive the null terminated ascii character string, netaddr,
923**    and convert to the Internet Protocol Network Address format.  Insert
924**    into the RPC address, indicated by argument rpc_addr.
925**
926**  INPUTS:
927**
928**      netaddr         String containing network address to insert into
929**                      RPC address.  It must contain an ASCII value in the
930**                      Internet dot notation, (a.b.c.d), format.
931**
932**  INPUTS/OUTPUTS:
933**
934**      rpc_addr        The address of a pointer to an RPC address where
935**                      the network address is to be inserted.
936**
937**  OUTPUTS:
938**
939**      status          A value indicating the status of the routine.
940**
941**      rpc_s_ok                  The call was successful.
942**      rpc_s_inval_net_addr      Invalid IP network address string passed
943**                                in netaddr
944**
945**
946**  IMPLICIT INPUTS:    none
947**
948**  IMPLICIT OUTPUTS:   none
949**
950**  FUNCTION VALUE:     none
951**
952**  SIDE EFFECTS:       none
953**
954**--
955**/
956
957INTERNAL void addr_set_netaddr
958(
959    unsigned_char_p_t       netaddr,
960    rpc_addr_p_t            *rpc_addr,
961    unsigned32              *status
962)
963{
964    rpc_ip_addr_p_t     ip_addr = (rpc_ip_addr_p_t) *rpc_addr;
965    boolean             numeric;
966#if (GETHOSTBYNAME_R_ARGS - 0) == 3
967#define he (&hbuf)
968    ATTRIBUTE_UNUSED struct hostent      hbuf;
969    ATTRIBUTE_UNUSED struct hostent_data hdbuf;
970#else
971    ATTRIBUTE_UNUSED struct hostent      *he;
972    ATTRIBUTE_UNUSED struct hostent      hbuf;
973    ATTRIBUTE_UNUSED char                buf[1024];
974    ATTRIBUTE_UNUSED int                 herr;
975#endif /* GETHOSTBYNAME_R_ARGS == 3 */
976
977    CODING_ERROR (status);
978
979    /*
980     * check to see if this is a request to remove the netaddr
981     */
982    if (netaddr == NULL || strlen ((char *) netaddr) == 0)
983    {
984        ip_addr->sa.sin_addr.s_addr = 0;
985        *status = rpc_s_ok;
986        return;
987    }
988
989    /*
990     * See if there's a leading "#" -- means numeric address must follow.
991     * Note we accept numeric addresses withOUT the "#" too.
992     */
993    numeric = (netaddr[0] == '#');
994    if (numeric)
995        netaddr++;
996
997    /*
998     * convert Internet dot notation address to network address
999     * formatted unsigned32 - check for validity
1000     */
1001    ip_addr->sa.sin_addr.s_addr = inet_addr ((char*) netaddr);
1002    if (ip_addr->sa.sin_addr.s_addr != (unsigned)-1)
1003    {
1004        *status = rpc_s_ok;
1005        return;
1006    }
1007
1008    if (numeric)
1009    {
1010        *status = rpc_s_inval_net_addr;
1011        return;
1012    }
1013
1014#if (GETHOSTBYNAME_R_ARGS - 0) == 6
1015    if (gethostbyname_r((char *)netaddr, &hbuf,
1016                        buf, sizeof(buf), &he, &herr) != 0)
1017#elif (GETHOSTBYNAME_R_ARGS - 0) == 5
1018    if ((he = gethostbyname_r((char *)netaddr, &hbuf, buf,
1019                              sizeof(buf), &herr)) == NULL)
1020#elif (GETHOSTBYNAME_R_ARGS - 0) == 3
1021    if (gethostbyname_r((char *)netaddr, &hbuf, &hdbuf) != 0)
1022#else
1023    /* As a last resort, fall back on gethostbyname */
1024    if((he = gethostbyname((char *)netaddr)) == NULL)
1025#endif /* GETHOSTBYNAME_R_ARGS */
1026    {
1027        *status = rpc_s_inval_net_addr;
1028        return;
1029    }
1030
1031    if (he == NULL)
1032    {
1033        *status = rpc_s_inval_net_addr;
1034        return;
1035    }
1036
1037    ip_addr->sa.sin_addr.s_addr = * (unsigned32 *) he->h_addr;
1038
1039    *status = rpc_s_ok;
1040}
1041
1042/*
1043**++
1044**
1045**  ROUTINE NAME:       addr_inq_netaddr
1046**
1047**  SCOPE:              INTERNAL - declared locally
1048**
1049**  DESCRIPTION:
1050**
1051**    From the RPC address indicated by arg., rpc_addr, examine the
1052**    IP network address.  Convert the network address from its network
1053**    format  to a NULL terminated ascii character string in IP dot
1054**    notation format.  The character string to be returned in the
1055**    memory segment pointed to by arg., netaddr.
1056**
1057**  INPUTS:
1058**
1059**      rpc_addr        The address of a pointer to an RPC address that
1060**                      is to be inspected.
1061**
1062**  INPUTS/OUTPUTS:
1063**
1064**
1065**  OUTPUTS:
1066**
1067**      netaddr         String pointer indicating where the network
1068**                      address string is to be placed.
1069**
1070**      status          A value indicating the status of the routine.
1071**
1072**          rpc_s_ok           The call was successful.
1073**
1074**  IMPLICIT INPUTS:    none
1075**
1076**  IMPLICIT OUTPUTS:   none
1077**
1078**  FUNCTION VALUE:     none
1079**
1080**  SIDE EFFECTS:       none
1081**
1082**--
1083**/
1084
1085INTERNAL void addr_inq_netaddr
1086(
1087    rpc_addr_p_t            rpc_addr,
1088    unsigned_char_t         **netaddr,
1089    unsigned32              *status
1090)
1091{
1092#define NA_SIZE 16      /* big enough for 255.255.255.255 */
1093
1094    rpc_ip_addr_p_t     ip_addr = (rpc_ip_addr_p_t) rpc_addr;
1095    unsigned8           *p;
1096
1097    CODING_ERROR (status);
1098
1099    RPC_MEM_ALLOC(
1100        *netaddr,
1101        unsigned_char_p_t,
1102        NA_SIZE,
1103        RPC_C_MEM_STRING,
1104        RPC_C_MEM_WAITOK);
1105
1106    /*
1107     * get an unsigned8 pointer to IP address - network format
1108     */
1109    p = (unsigned8 *) &(ip_addr->sa.sin_addr.s_addr);
1110
1111    /*
1112     * convert IP address to IP dot notation string - (eg, 16.0.0.4)
1113     * placed in buffer indicated by arg.netaddr.
1114     */
1115    RPC__IP_NETWORK_SPRINTF((char *) *netaddr, "%d.%d.%d.%d",
1116        UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
1117
1118    *status = rpc_s_ok;
1119}
1120
1121/*
1122**++
1123**
1124**  ROUTINE NAME:       addr_set_options
1125**
1126**  SCOPE:              INTERNAL - declared locally
1127**
1128**  DESCRIPTION:
1129**
1130**     Receive a NULL terminated network options string and insert
1131**     into the RPC address indicated by art., rpc_addr.
1132**
1133**      NOTE - there are no options used with the IP service this
1134**             routine is here only to serve as a stub.
1135**
1136**  INPUTS:
1137**
1138**      options         String containing network options to insert
1139**                      into  RPC address.
1140**
1141**  INPUTS/OUTPUTS:
1142**
1143**      rpc_addr        The address of a pointer to an RPC address where
1144**                      the network options strig is to be inserted.
1145**  OUTPUTS:
1146**
1147**      status          A value indicating the status of the routine.
1148**
1149**          rpc_s_ok           The call was successful.
1150**
1151**  IMPLICIT INPUTS:    none
1152**
1153**  IMPLICIT OUTPUTS:   none
1154**
1155**  FUNCTION VALUE:     none
1156**
1157**  SIDE EFFECTS:       none
1158**
1159**--
1160**/
1161
1162INTERNAL void addr_set_options
1163(
1164    unsigned_char_p_t       network_options ATTRIBUTE_UNUSED,
1165    rpc_addr_p_t            *rpc_addr ATTRIBUTE_UNUSED,
1166    unsigned32              *status
1167)
1168{
1169    *status = rpc_s_ok;
1170}
1171
1172/*
1173**++
1174**
1175**  ROUTINE NAME:       addr_inq_options
1176**
1177**  SCOPE:              INTERNAL - declared locally
1178**
1179**  DESCRIPTION:
1180**
1181**      Extract the network options from the RPC address pointed to
1182**      by rpc_addr and convert to a NULL terminated string placed
1183**      in a buffer indicated by the options arg.
1184**
1185**      NOTE - there are no options used with the IP service this
1186**             routine is here only to serve as a stub.
1187**
1188**  INPUTS:
1189**
1190**      rpc_addr        The address of a pointer to an RPC address that
1191**                      is to be inspected.
1192**
1193**  INPUTS/OUTPUTS:     none
1194**
1195**  OUTPUTS:
1196**
1197**      options         String pointer indicating where the network
1198**                      options string is to be placed.
1199**
1200**
1201**      status          A value indicating the status of the routine.
1202**
1203**          rpc_s_ok           The call was successful.
1204**
1205**  IMPLICIT INPUTS:    none
1206**
1207**  IMPLICIT OUTPUTS:   none
1208**
1209**  FUNCTION VALUE:     none
1210**
1211**  SIDE EFFECTS:       none
1212**
1213**--
1214**/
1215
1216INTERNAL void addr_inq_options
1217(
1218    rpc_addr_p_t            rpc_addr ATTRIBUTE_UNUSED,
1219    unsigned_char_t         **network_options,
1220    unsigned32              *status
1221)
1222{
1223    RPC_MEM_ALLOC(
1224        *network_options,
1225        unsigned_char_p_t,
1226        sizeof(unsigned32),     /* only really need 1 byte */
1227        RPC_C_MEM_STRING,
1228        RPC_C_MEM_WAITOK);
1229
1230    *network_options[0] = 0;
1231    *status = rpc_s_ok;
1232}
1233
1234/*
1235**++
1236**
1237**  ROUTINE NAME:       inq_max_tsdu
1238**
1239**  SCOPE:              INTERNAL - declared locally
1240**
1241**  DESCRIPTION:
1242**
1243**  INPUTS:
1244**
1245**      naf_id          Network Address Family ID serves
1246**                      as index into EPV for IP routines.
1247**
1248**      iftype          Network interface type ID
1249**
1250**      protocol        Network protocol ID
1251**
1252**  INPUTS/OUTPUTS:     none
1253**
1254**  OUTPUTS:
1255**
1256**      max_tsdu
1257**
1258**      status          A value indicating the status of the routine.
1259**
1260**  IMPLICIT INPUTS:    none
1261**
1262**  IMPLICIT OUTPUTS:   none
1263**
1264**  FUNCTION VALUE:     none
1265**
1266**  SIDE EFFECTS:       none
1267**
1268**--
1269**/
1270
1271INTERNAL void inq_max_tsdu
1272(
1273    rpc_naf_id_t            naf_id ATTRIBUTE_UNUSED,
1274    rpc_network_if_id_t     iftype,
1275    rpc_network_protocol_id_t protocol,
1276    unsigned32              *max_tsdu,
1277    unsigned32              *status
1278)
1279{
1280    if (iftype == RPC_C_NETWORK_IF_ID_DGRAM &&
1281        protocol == RPC_C_NETWORK_PROTOCOL_ID_UDP)
1282    {
1283        *max_tsdu = RPC_C_IP_UDP_MAX_TSDU;
1284    }
1285    else
1286    {
1287        assert(false);      /* !!! */
1288    }
1289
1290#ifdef DEBUG
1291    if (RPC_DBG (rpc_es_dbg_ip_max_tsdu, 1))
1292    {
1293        *max_tsdu = ((unsigned32)
1294            (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_tsdu])) * 1024;
1295    }
1296#endif
1297
1298    *status = rpc_s_ok;
1299}
1300
1301/*
1302**++
1303**
1304**  ROUTINE NAME:       addr_compare
1305**
1306**  SCOPE:              INTERNAL - declared locally
1307**
1308**  DESCRIPTION:
1309**
1310**  Determine if two address are equal.
1311**
1312**  INPUTS:
1313**
1314**      addr1
1315**
1316**      addr2
1317**
1318**  INPUTS/OUTPUTS:     none
1319**
1320**  OUTPUTS:
1321**
1322**      status          A value indicating the status of the routine.
1323**
1324**  IMPLICIT INPUTS:    none
1325**
1326**  IMPLICIT OUTPUTS:   none
1327**
1328**  FUNCTION VALUE:
1329**
1330**      return          Boolean; true if address are the same.
1331**
1332**  SIDE EFFECTS:       none
1333**
1334**--
1335**/
1336
1337INTERNAL boolean addr_compare
1338(
1339    rpc_addr_p_t            addr1,
1340    rpc_addr_p_t            addr2,
1341    unsigned32              *status ATTRIBUTE_UNUSED
1342)
1343{
1344    rpc_ip_addr_p_t     ip_addr1 = (rpc_ip_addr_p_t) addr1;
1345    rpc_ip_addr_p_t     ip_addr2 = (rpc_ip_addr_p_t) addr2;
1346
1347    if (ip_addr1->sa.sin_family == ip_addr2->sa.sin_family &&
1348        ip_addr1->sa.sin_port == ip_addr2->sa.sin_port &&
1349        ip_addr1->sa.sin_addr.s_addr == ip_addr2->sa.sin_addr.s_addr &&
1350        ip_addr1->sa.sin_addr.s_addr == ip_addr2->sa.sin_addr.s_addr)
1351    {
1352        return true;
1353    }
1354    else
1355    {
1356        return false;
1357    }
1358}
1359
1360
1361/*
1362**++
1363**
1364**  ROUTINE NAME:       inq_max_pth_unfrag_tpdu
1365**
1366**  SCOPE:              INTERNAL - declared locally
1367**
1368**  DESCRIPTION:
1369**
1370**  INPUTS:
1371**
1372**      naf_id          Network Address Family ID serves
1373**                      as index into EPV for IP routines.
1374**
1375**      iftype          Network interface type ID
1376**
1377**      protocol        Network protocol ID
1378**
1379**  INPUTS/OUTPUTS:     none
1380**
1381**  OUTPUTS:
1382**
1383**      max_tpdu
1384**
1385**      status          A value indicating the status of the routine.
1386**
1387**  IMPLICIT INPUTS:    none
1388**
1389**  IMPLICIT OUTPUTS:   none
1390**
1391**  FUNCTION VALUE:     none
1392**
1393**  SIDE EFFECTS:       none
1394**
1395**--
1396**/
1397
1398INTERNAL void inq_max_pth_unfrag_tpdu
1399(
1400    rpc_addr_p_t            rpc_addr ATTRIBUTE_UNUSED,
1401    rpc_network_if_id_t     iftype,
1402    rpc_network_protocol_id_t protocol,
1403    unsigned32              *max_tpdu,
1404    unsigned32              *status
1405)
1406{
1407    if (iftype == RPC_C_NETWORK_IF_ID_DGRAM &&
1408        protocol == RPC_C_NETWORK_PROTOCOL_ID_UDP)
1409    {
1410        *max_tpdu = RPC_C_IP_UDP_MAX_PTH_UNFRG_TPDU;
1411    }
1412    else
1413    {
1414        assert(false);      /* !!! */
1415    }
1416
1417#ifdef DEBUG
1418    if (RPC_DBG (rpc_es_dbg_ip_max_pth_unfrag_tpdu, 1))
1419    {
1420        *max_tpdu = ((unsigned32)
1421            (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_pth_unfrag_tpdu])) * 32;
1422    }
1423#endif
1424
1425    *status = rpc_s_ok;
1426}
1427
1428/*
1429**++
1430**
1431**  ROUTINE NAME:       inq_max_loc_unfrag_tpdu
1432**
1433**  SCOPE:              INTERNAL - declared locally
1434**
1435**  DESCRIPTION:
1436**
1437**  INPUTS:
1438**
1439**      naf_id          Network Address Family ID serves
1440**                      as index into EPV for IP routines.
1441**
1442**      iftype          Network interface type ID
1443**
1444**      protocol        Network protocol ID
1445**
1446**  INPUTS/OUTPUTS:     none
1447**
1448**  OUTPUTS:
1449**
1450**      max_tpdu
1451**
1452**      status          A value indicating the status of the routine.
1453**
1454**  IMPLICIT INPUTS:    none
1455**
1456**  IMPLICIT OUTPUTS:   none
1457**
1458**  FUNCTION VALUE:     none
1459**
1460**  SIDE EFFECTS:       none
1461**
1462**--
1463**/
1464
1465INTERNAL void inq_max_loc_unfrag_tpdu
1466(
1467    rpc_naf_id_t            naf_id ATTRIBUTE_UNUSED,
1468    rpc_network_if_id_t     iftype,
1469    rpc_network_protocol_id_t protocol,
1470    unsigned32              *max_tpdu,
1471    unsigned32              *status
1472)
1473{
1474    if (iftype == RPC_C_NETWORK_IF_ID_DGRAM &&
1475        protocol == RPC_C_NETWORK_PROTOCOL_ID_UDP)
1476    {
1477        *max_tpdu = RPC_C_IP_UDP_MAX_LOC_UNFRG_TPDU;
1478    }
1479    else
1480    {
1481        assert(false);      /* !!! */
1482    }
1483
1484#ifdef DEBUG
1485    if (RPC_DBG (rpc_es_dbg_ip_max_loc_unfrag_tpdu, 1))
1486    {
1487        *max_tpdu = ((unsigned32)
1488            (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_loc_unfrag_tpdu])) * 32;
1489    }
1490#endif
1491
1492    *status = rpc_s_ok;
1493}
1494
1495/*
1496**++
1497**
1498**  ROUTINE NAME:       desc_inq_network
1499**
1500**  SCOPE:              INTERNAL - declared locally
1501**
1502**  DESCRIPTION:
1503**
1504**  This routine is responsible for "reverse-engineering" the parameters to
1505**  the original socket call that was made to create the socket "desc".
1506**
1507**  INPUTS:
1508**
1509**      desc            socket descriptor to query
1510**
1511**  INPUTS/OUTPUTS:
1512**
1513**  OUTPUTS:
1514**
1515**      socket_type     network interface type id
1516**
1517**      protocol_id     network protocol family id
1518**
1519**      status          status returned
1520**                              rpc_s_ok
1521**                              rpc_s_cant_get_if_id
1522**
1523**  IMPLICIT INPUTS:    none
1524**
1525**  IMPLICIT OUTPUTS:   none
1526**
1527**  FUNCTION VALUE:     none
1528**
1529**  SIDE EFFECTS:       none
1530**
1531**--
1532**/
1533
1534INTERNAL void desc_inq_network
1535(
1536    rpc_socket_t              desc,
1537    rpc_network_if_id_t       *socket_type,
1538    rpc_network_protocol_id_t *protocol_id,
1539    unsigned32                *status
1540)
1541{
1542    rpc_socket_error_t serr;
1543
1544    CODING_ERROR (status);
1545
1546    /*
1547     * Get the socket type.
1548     */
1549
1550    serr = rpc__socket_get_if_id (desc, socket_type);
1551    if (RPC_SOCKET_IS_ERR (serr))
1552    {
1553        RPC_DBG_GPRINTF (("rpc__socket_get_if_id: serr=%d\n",serr));
1554        *status = rpc_s_cant_get_if_id;
1555        return;
1556    }
1557
1558    /*
1559     * For now, there is a one to one relationship between the protocol family
1560     * and the socket type.
1561     */
1562
1563    switch ((int)(*socket_type))
1564    {
1565        case SOCK_STREAM:       *protocol_id = RPC_C_NETWORK_PROTOCOL_ID_TCP;
1566                                break;
1567
1568        case SOCK_DGRAM:        *protocol_id = RPC_C_NETWORK_PROTOCOL_ID_UDP;
1569                                break;
1570
1571        default:
1572            /*
1573             * rpc_m_unk_sock_type
1574             * "(%s) Unknown socket type"
1575             */
1576            rpc_dce_svc_printf (
1577                __FILE__, __LINE__,
1578                "%s",
1579                rpc_svc_general,
1580                svc_c_sev_fatal | svc_c_action_abort,
1581                rpc_m_unk_sock_type,
1582                "desc_inq_network" );
1583            break;
1584    }
1585
1586    *status = rpc_s_ok;
1587}
1588
1589
1590/*
1591**++
1592**
1593**  ROUTINE NAME:       set_pkt_nodelay
1594**
1595**  SCOPE:              INTERNAL - declared locally
1596**
1597**  DESCRIPTION:
1598**
1599**  INPUTS:
1600**
1601**      desc            The network descriptor to apply the nodelay
1602**                      option to.
1603**
1604**  INPUTS/OUTPUTS:     none
1605**
1606**  OUTPUTS:
1607**
1608**      status          A value indicating the status of the routine.
1609**
1610**  IMPLICIT INPUTS:    none
1611**
1612**  IMPLICIT OUTPUTS:   none
1613**
1614**  FUNCTION VALUE:     none
1615**
1616**  SIDE EFFECTS:       none
1617**
1618**--
1619**/
1620
1621INTERNAL void set_pkt_nodelay
1622(
1623    rpc_socket_t            sock,
1624    unsigned32              *status
1625)
1626{
1627    int                 err;
1628    int                 delay = 1;
1629    /* FIXME: this really ought to become a new socket vtbl entry point */
1630    int                 desc = rpc__socket_get_select_desc(sock);
1631
1632    /*
1633     * Assume this is a TCP socket and corresponding connection. If
1634     * not the setsockopt will fail.
1635     */
1636    err = setsockopt (desc,
1637                      IPPROTO_TCP,
1638                      TCP_NODELAY,
1639                      (char *) &delay,
1640                      sizeof (delay));
1641    if (err < 0)
1642    {
1643        *status = rpc_s_cannot_set_nodelay;
1644    }
1645    else
1646    {
1647        *status = rpc_s_ok;
1648    }
1649}
1650
1651
1652/*
1653**++
1654**
1655**  ROUTINE NAME:       is_connect_closed
1656**
1657**  SCOPE:              INTERNAL - declared locally
1658**
1659**  DESCRIPTION:
1660**
1661**      This routine is called when a recv on a sequenced packet
1662**      socket has returned zero bytes. Since TCP does not support
1663**      sequenced sockets the routine is a no-op. "true" is returned
1664**      because zero bytes received on a stream socket does mean the
1665**      connection is closed.
1666**
1667**  INPUTS:
1668**
1669**      desc            The network descriptor representing the connection.
1670**
1671**  INPUTS/OUTPUTS:     none
1672**
1673**  OUTPUTS:
1674**
1675**      status          A value indicating the status of the routine.
1676**
1677**  IMPLICIT INPUTS:    none
1678**
1679**  IMPLICIT OUTPUTS:   none
1680**
1681**  FUNCTION VALUE:
1682**
1683**      boolean         true if the connection is closed, false otherwise.
1684**
1685**  SIDE EFFECTS:       none
1686**
1687**--
1688**/
1689
1690INTERNAL boolean is_connect_closed
1691(
1692    rpc_socket_t            desc ATTRIBUTE_UNUSED,
1693    unsigned32              *status
1694)
1695{
1696    *status = rpc_s_ok;
1697    return (true);
1698}
1699
1700
1701/*
1702**++
1703**
1704**  ROUTINE NAME:       tower_flrs_from_addr
1705**
1706**  SCOPE:              INTERNAL - declared locally
1707**
1708**  DESCRIPTION:
1709**
1710**  Creates the lower tower floors from an RPC addr.
1711**
1712**  INPUTS:
1713**
1714**      rpc_addr	RPC addr to convert to lower tower floors.
1715**
1716**  INPUTS/OUTPUTS:     none
1717**
1718**  OUTPUTS:
1719**
1720**      lower_flrs      The returned lower tower floors.
1721**
1722**      status          A value indicating the return status of the routine.
1723**
1724**  IMPLICIT INPUTS:    none
1725**
1726**  IMPLICIT OUTPUTS:   none
1727**
1728**  FUNCTION VALUE:     void
1729**
1730**  SIDE EFFECTS:       none
1731**
1732**--
1733**/
1734
1735INTERNAL void tower_flrs_from_addr
1736(
1737    rpc_addr_p_t       rpc_addr,
1738    twr_p_t            *lower_flrs,
1739    unsigned32         *status
1740)
1741{
1742    unsigned32    net_prot_id;
1743
1744    CODING_ERROR (status);
1745
1746#ifdef RPC_NO_TOWER_SUPPORT
1747
1748    *status = rpc_s_coding_error;
1749
1750#else
1751
1752#if 0
1753    /*
1754     * The use of a temporary lower floors twr_t is in anticipation
1755     * of the twr_* routines belonging to a separate library with
1756     * their own memory allocation. In that case, twr_* allocates
1757     * memory for returning the lower towers, and we must copy from
1758     * twr_* memory into our (rpc) memory. After the copy, we free
1759     * the twr_* allocated memory.
1760     *
1761     * For now, twr_* routines also use RPC_MEM_ALLOC and RPC_MEM_FREE,
1762     * so we'll skip the extra copy.
1763     */
1764    twr_p_t     temp_lower_flrs;
1765#endif
1766
1767    /*
1768     * Get the network protocol id (aka transport layer protocol)
1769     * for this RPC addr.
1770     */
1771    net_prot_id = RPC_PROTSEQ_INQ_NET_PROT_ID(rpc_addr->rpc_protseq_id);
1772
1773    /*
1774     * Convert sockaddr to lower tower floors.
1775     */
1776    twr_ip_lower_flrs_from_sa (net_prot_id, (sockaddr_t *) &(rpc_addr->sa),
1777#if 0
1778        &temp_lower_flrs,
1779#else
1780        lower_flrs,
1781#endif
1782        status);
1783
1784    if (*status != twr_s_ok)
1785    {
1786        return;
1787    }
1788
1789#if 0
1790    /*
1791     * Allocate a tower structure to hold the wire (and nameservice)
1792     * representation of the lower tower floors returned from twr_*().
1793     *
1794     * The size includes the sizof twr_t + length of the tower floors
1795     * returned from twr_ip_lower_flrs_from_sa - 1 (for tower_octet_string[0].
1796     */
1797    RPC_MEM_ALLOC (
1798        *lower_flrs,
1799        twr_p_t,
1800        sizeof(twr_t) + temp_lower_flrs->tower_length - 1,
1801        RPC_C_MEM_TOWER,
1802        RPC_C_MEM_WAITOK );
1803
1804    /*
1805     * Set the tower length to the length of the tower flrs returnd from
1806     * twr_ip_lower_flrs_from_sa.
1807     */
1808    (*lower_flrs)->tower_length = temp_lower_flrs->tower_length;
1809
1810    /*
1811     * Copy the lower tower floors to the tower octet string.
1812     */
1813    memcpy ((*lower_flrs)->tower_octet_string,
1814        temp_lower_flrs->tower_octet_string,
1815        temp_lower_flrs->tower_length);
1816
1817    /*
1818     * Free the twr_ip_lower_flrs_from_sa allocated memory.
1819     */
1820    RPC_MEM_FREE (temp_lower_flrs, RPC_C_MEM_TOWER);
1821#endif
1822
1823#endif
1824
1825    return;
1826}
1827
1828/*
1829**++
1830**
1831**  ROUTINE NAME:       tower_flrs_to_addr
1832**
1833**  SCOPE:              INTERNAL - declared locally
1834**
1835**  DESCRIPTION:
1836**
1837**  Creates an RPC addr from a protocol tower.
1838**
1839**  INPUTS:
1840**
1841**      tower_octet_string
1842**                      Protocol tower whose floors are used to construct
1843**                      an RPC addr
1844**
1845**  INPUTS/OUTPUTS:     none
1846**
1847**  OUTPUTS:
1848**
1849**      rpc_addr	RPC addr constructed from a protocol tower.
1850**
1851**      status          A value indicating the return status of the routine:
1852**                          rpc_s_ok
1853**
1854**  IMPLICIT INPUTS:    none
1855**
1856**  IMPLICIT OUTPUTS:   none
1857**
1858**  FUNCTION VALUE:     void
1859**
1860**  SIDE EFFECTS:       none
1861**
1862**--
1863**/
1864
1865INTERNAL void tower_flrs_to_addr
1866(
1867    byte_p_t           tower_octet_string,
1868    rpc_addr_p_t       *rpc_addr,
1869    unsigned32         *status
1870)
1871{
1872    sockaddr_t    *sa;
1873    unsigned32    sa_len;
1874
1875    CODING_ERROR (status);
1876
1877#ifdef RPC_NO_TOWER_SUPPORT
1878
1879    *status = rpc_s_coding_error;
1880
1881#else
1882
1883    /*
1884     * Convert the lower floors of a tower to a sockaddr.
1885     */
1886    twr_ip_lower_flrs_to_sa (
1887        tower_octet_string,        /* tower octet string (has flr count). */
1888        &sa,                       /* returned sockaddr     */
1889        &sa_len,                   /* returned sockaddr len */
1890        status);
1891
1892    if (*status != twr_s_ok)
1893    {
1894        return;
1895    }
1896
1897    /*
1898     * Call the common NAF routine to create an RPC addr from a sockaddr.
1899     * (rpc__naf_addr_from_sa doesn't dispatch to a naf-specific routine.)
1900     */
1901    rpc__naf_addr_from_sa (sa, sa_len, rpc_addr, status);
1902
1903    /*
1904     * Always free the twr_ip_lower_flrs_to_sa allocated memory - regardless
1905     * of the status from rpc__naf_addr_from_sa.
1906     */
1907    RPC_MEM_FREE (sa, RPC_C_MEM_SOCKADDR);
1908
1909#endif /* RPC_NO_TOWER_SUPPORT */
1910
1911    /*
1912     * Return whatever status we had.
1913     */
1914    return;
1915}
1916
1917
1918/*
1919**++
1920**
1921**  ROUTINE NAME:       desc_inq_peer_addr
1922**
1923**  SCOPE:              INTERNAL - declared locally
1924**
1925**  DESCRIPTION:
1926**
1927**    Receive a socket descriptor which is queried to obtain family,
1928**    remote endpoint and remote network address.  If this information appears valid
1929**    for an DECnet IV address,  space is allocated for an RPC address which
1930**    is initialized with the information obtained from this socket.  The
1931**    address indicating the created RPC address is returned in, arg., rpc_addr.
1932**
1933**  INPUTS:
1934**
1935**      protseq_id             Protocol Sequence ID representing a
1936**                             particular Network Address Family,
1937**                             its Transport Protocol, and type.
1938**
1939**      desc                   Descriptor, indicating a socket that
1940**                             has been created on the local operating
1941**                             platform.
1942**
1943**  INPUTS/OUTPUTS:
1944**
1945**      rpc_addr        The address of a pointer where the RPC address
1946**                      created by this routine will be indicated.
1947**
1948**  OUTPUTS:
1949**
1950**      status          A value indicating the status of the routine.
1951**
1952**          rpc_s_ok               The call was successful.
1953**
1954**          rpc_s_no_memory         Call to malloc failed to allocate memory.
1955**
1956**          rpc_s_cant_get_peername Call to getpeername failed.
1957**
1958**          rpc_s_invalid_naf_id   Socket that arg desc refers is not DECnet IV.
1959**
1960**          Any of the RPC Protocol Service status codes.
1961**
1962**  IMPLICIT INPUTS:    none
1963**
1964**  IMPLICIT OUTPUTS:   none
1965**
1966**  FUNCTION VALUE:     none
1967**
1968**  SIDE EFFECTS:       none
1969**
1970**--
1971**/
1972
1973INTERNAL void desc_inq_peer_addr
1974(
1975    rpc_protseq_id_t        protseq_id,
1976    rpc_socket_t            desc,
1977    rpc_addr_p_t            *rpc_addr,
1978    unsigned32              *status
1979)
1980{
1981    rpc_socket_error_t  serr;
1982
1983    CODING_ERROR (status);
1984
1985    /*
1986     * allocate memory for the new RPC address
1987     */
1988    RPC_MEM_ALLOC (*rpc_addr,
1989                   rpc_addr_p_t,
1990                   sizeof (rpc_ip_addr_t),
1991                   RPC_C_MEM_RPC_ADDR,
1992                   RPC_C_MEM_WAITOK);
1993
1994    /*
1995     * successful malloc
1996     */
1997    if (*rpc_addr == NULL)
1998    {
1999        *status = rpc_s_no_memory;
2000        return;
2001    }
2002
2003    /*
2004     * insert individual parameters into RPC address
2005     */
2006    (*rpc_addr)->rpc_protseq_id = protseq_id;
2007    (*rpc_addr)->len = sizeof (struct sockaddr_in);
2008
2009    /*
2010     * Get the peer address (name).
2011     *
2012     * If we encounter an error, free the address structure and return
2013     * the status from the getpeername() call, not the free() call.
2014     */
2015
2016    serr = rpc__socket_getpeername (desc, *rpc_addr);
2017    if (RPC_SOCKET_IS_ERR (serr))
2018    {
2019        RPC_MEM_FREE (*rpc_addr, RPC_C_MEM_RPC_ADDR);
2020        *rpc_addr = (rpc_addr_p_t)NULL;
2021        *status = rpc_s_cant_getpeername;
2022    }
2023    else
2024    {
2025        *status = rpc_s_ok;
2026    }
2027}
2028
2029
2030/*
2031**++
2032**
2033**  ROUTINE NAME:       set_port_restriction
2034**
2035**  SCOPE:              INTERNAL
2036**
2037**  DESCRIPTION:
2038**
2039**  Builds an rpc_port_restriction_list_t and glues it into the
2040**  rpc_protseq_id_elt_t in the rpc_g_protseq_id[] list.
2041**
2042**  INPUTS:
2043**
2044**      protseq_id
2045**                      The protocol sequence id to set port restriction
2046**                      on.
2047**      n_elements
2048**                      The number of port ranges passed in.
2049**
2050**      first_port_name_list
2051**                      An array of pointers to strings containing the
2052**                      lower bound port names.
2053**
2054**      last_port_name_list
2055**                      An array of pointers to strings containing the
2056**                      upper bound port names.
2057**
2058**  INPUTS/OUTPUTS:     none
2059**
2060**  OUTPUTS:
2061**
2062**      status
2063**
2064**  IMPLICIT INPUTS:    none
2065**
2066**  IMPLICIT OUTPUTS:   none
2067**
2068**  FUNCTION VALUE:     void
2069**
2070**  SIDE EFFECTS:       none
2071**
2072**--
2073**/
2074
2075INTERNAL void set_port_restriction
2076(
2077     rpc_protseq_id_t            protseq_id,
2078     unsigned32                  n_elements,
2079     unsigned_char_p_t           *first_port_name_list,
2080     unsigned_char_p_t           *last_port_name_list,
2081     unsigned32                  *status
2082)
2083{
2084
2085    rpc_port_restriction_list_p_t list_p;
2086    rpc_port_range_element_p_t   range_elements;
2087    unsigned32                   i;
2088
2089    CODING_ERROR (status);
2090
2091    /*
2092     * It is only meaningful to do this once per protocol sequence.
2093     */
2094
2095    if (rpc_g_protseq_id [protseq_id].port_restriction_list != NULL)
2096    {
2097        *status = rpc_s_already_registered;
2098        return;
2099    }
2100
2101    /*
2102     * Allocate the port_restriction_list.
2103     */
2104
2105    RPC_MEM_ALLOC
2106        (list_p,
2107         rpc_port_restriction_list_p_t,
2108         sizeof (rpc_port_restriction_list_t),
2109         RPC_C_MEM_PORT_RESTRICT_LIST,
2110         RPC_C_MEM_WAITOK);
2111
2112    if (list_p == NULL)
2113    {
2114        *status = rpc_s_no_memory;
2115        return;
2116    }
2117
2118    /*
2119     * Allocate the port_range_element vector.
2120     */
2121
2122    RPC_MEM_ALLOC (range_elements,
2123                   rpc_port_range_element_p_t,
2124                   sizeof (rpc_port_range_element_t) * n_elements,
2125                   RPC_C_MEM_PORT_RANGE_ELEMENTS,
2126                   RPC_C_MEM_WAITOK);
2127
2128    if (range_elements == NULL)
2129    {
2130        *status = rpc_s_no_memory;
2131        return;
2132    }
2133
2134    /*
2135     * Initialize the rpc_port_restriction_list
2136     */
2137
2138    list_p -> n_tries = 0;
2139    list_p -> n_elements = n_elements;
2140    list_p -> range_elements = range_elements;
2141
2142    /*
2143     * Loop and initialize the range element list.
2144     */
2145
2146    for (i = 0; i < n_elements; i++)
2147    {
2148	unsigned long low, high;
2149        if ((RPC__IP_ENDPOINT_SSCANF
2150             ((char *) first_port_name_list[i], "%lu", &low)
2151             != 1)       ||
2152            (RPC__IP_ENDPOINT_SSCANF
2153             ((char *) last_port_name_list[i], "%lu", &high)
2154             != 1)       ||
2155            (low > high))
2156        {
2157            RPC_MEM_FREE (list_p, RPC_C_MEM_PORT_RESTRICT_LIST);
2158            RPC_MEM_FREE (range_elements, RPC_C_MEM_PORT_RANGE_ELEMENTS);
2159
2160            *status = rpc_s_invalid_endpoint_format;
2161
2162            return;
2163        }                               /* error from scanf */
2164
2165	range_elements[i].low = (unsigned32) low;
2166	range_elements[i].high = (unsigned32) high;
2167
2168        list_p -> n_tries +=
2169            range_elements[i].high - range_elements[i].low + 1;
2170    }                                   /* for i */
2171
2172    /*
2173     * Randomly choose a starting range and a port within the range.
2174     */
2175
2176    list_p -> current_range_element = RPC_RANDOM_GET (0, n_elements - 1);
2177    i = list_p -> current_range_element;
2178
2179    list_p -> current_port_in_range =
2180        RPC_RANDOM_GET (range_elements[i].low, range_elements[i].high);
2181
2182    /*
2183     * Everything was successful.  Wire the port_restriction_list into the
2184     * protseq descriptor table.
2185     */
2186
2187    rpc_g_protseq_id [protseq_id].port_restriction_list = list_p;
2188    *status = rpc_s_ok;
2189
2190}                                       /* set_port_restriction */
2191
2192
2193/*
2194**++
2195**
2196**  ROUTINE NAME:       get_next_restricted_port
2197**
2198**  SCOPE:              INTERNAL
2199**
2200**  DESCRIPTION:
2201**
2202**  Returns the next restricted port in a sequence.  There is no guarantee
2203**  that the port is available, that is up to bind() to determine.
2204**
2205**  INPUTS:
2206**
2207**      protseq_id
2208**                      The protocol sequence id to get the port on.
2209**
2210**  INPUTS/OUTPUTS:     none
2211**
2212**  OUTPUTS:
2213**
2214**      port_name
2215**                      An IP port name as a text string.
2216**      status
2217**
2218**  IMPLICIT INPUTS:    none
2219**
2220**  IMPLICIT OUTPUTS:   none
2221**
2222**  FUNCTION VALUE:     void
2223**
2224**  SIDE EFFECTS:       none
2225**
2226**--
2227**/
2228
2229INTERNAL void get_next_restricted_port
2230(
2231    rpc_protseq_id_t           protseq_id,
2232     unsigned_char_p_t          *port_name,
2233     unsigned32                 *status
2234)
2235{
2236
2237    rpc_port_restriction_list_p_t list_p;
2238    rpc_port_range_element_p_t  range_p;
2239
2240    CODING_ERROR (status);
2241
2242    /*
2243     * Validate that this protocol sequence has a port restriction.
2244     */
2245
2246    list_p = rpc_g_protseq_id [protseq_id].port_restriction_list;
2247
2248    if (list_p == NULL)
2249    {
2250        /*
2251         * Return an error to tell the caller that there is no range
2252         * restriction on this protocol sequence.
2253         */
2254
2255        *status = rpc_s_invalid_arg;
2256        return;
2257    }
2258
2259    /*
2260     * Alloc a string and return to caller.
2261     */
2262
2263    RPC_MEM_ALLOC
2264        (*port_name,
2265         unsigned_char_p_t,
2266         RPC_C_ENDPOINT_IP_MAX,
2267         RPC_C_MEM_STRING,
2268         RPC_C_MEM_WAITOK);
2269
2270    RPC__IP_ENDPOINT_SPRINTF
2271        ((char *) *port_name, "%lu", (unsigned long) list_p -> current_port_in_range);
2272
2273    /*
2274     * Increment to the next restricted port number.  Handle wrapping
2275     * beyond end of this range.
2276     */
2277
2278    range_p = (rpc_port_range_element_p_t) list_p -> range_elements +
2279        list_p -> current_range_element;
2280
2281    if (++ (list_p -> current_port_in_range) > range_p -> high)
2282    {
2283        /*
2284         * Advance to next range and wraparound as needed.
2285         */
2286
2287        list_p -> current_range_element =
2288            (++ list_p -> current_range_element) % (list_p -> n_elements);
2289
2290        range_p = (rpc_port_range_element_p_t) list_p -> range_elements +
2291            list_p -> current_range_element;
2292
2293        /*
2294         * Set next port in new range to the lowest in that range.
2295         */
2296
2297        list_p -> current_port_in_range = range_p -> low;
2298
2299    }                                   /* wrapped to end of range */
2300
2301    /*
2302     * Success
2303     */
2304
2305    *status = rpc_s_ok;
2306}                                       /* get_next_restricted_port */
2307
2308/*
2309**++
2310**
2311**  ROUTINE NAME:       inq_max_frag_size
2312**
2313**  SCOPE:              INTERNAL - declared locally
2314**
2315**  DESCRIPTION:
2316**
2317**  INPUTS:
2318**
2319**      naf_id          Network Address Family ID serves
2320**                      as index into EPV for IP routines.
2321**
2322**      iftype          Network interface type ID
2323**
2324**      protocol        Network protocol ID
2325**
2326**  INPUTS/OUTPUTS:     none
2327**
2328**  OUTPUTS:
2329**
2330**      max_tpdu
2331**
2332**      status          A value indicating the status of the routine.
2333**
2334**  IMPLICIT INPUTS:    none
2335**
2336**  IMPLICIT OUTPUTS:   none
2337**
2338**  FUNCTION VALUE:     none
2339**
2340**  SIDE EFFECTS:       none
2341**
2342**--
2343**/
2344
2345INTERNAL void inq_max_frag_size
2346(
2347 rpc_addr_p_t rpc_addr,
2348 unsigned32   *max_frag_size,
2349 unsigned32   *status
2350)
2351{
2352    boolean     flag;
2353    unsigned32  lstatus;
2354
2355    /*
2356     * This should be called from ncadg_ip_udp only.
2357     */
2358    if (RPC_PROTSEQ_INQ_NET_IF_ID(rpc_addr->rpc_protseq_id)
2359          != RPC_C_NETWORK_IF_ID_DGRAM
2360        || RPC_PROTSEQ_INQ_NET_PROT_ID(rpc_addr->rpc_protseq_id)
2361            != RPC_C_NETWORK_PROTOCOL_ID_UDP)
2362    {
2363        assert(false);      /* !!! */
2364    }
2365
2366    *status = rpc_s_ok;
2367
2368    flag = rpc__ip_is_local_addr (rpc_addr, &lstatus);
2369    if (lstatus == rpc_s_ok && flag)
2370    {
2371        *max_frag_size = RPC_C_IP_UDP_MAX_LOCAL_FRAG_SIZE;
2372#ifdef DEBUG
2373        switch (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_loc_unfrag_tpdu])
2374        {
2375        case 0:
2376            break;
2377        case 1:
2378            *max_frag_size = RPC_C_IP_UDP_MAX_LOC_UNFRG_TPDU;
2379            break;
2380        case 2:
2381            *max_frag_size = RPC_C_FDDI_MAX_DATA_SIZE -
2382                (RPC_C_IP_LLC_SIZE + RPC_C_IP_HDR_SIZE +
2383                 RPC_C_IP_OPTS_SIZE + RPC_C_UDP_HDR_SIZE);
2384            break;
2385        case 3:
2386            *max_frag_size = 4608 -
2387                (RPC_C_IP_LLC_SIZE + RPC_C_IP_HDR_SIZE +
2388                 RPC_C_IP_OPTS_SIZE + RPC_C_UDP_HDR_SIZE);
2389            break;
2390        default:
2391            if (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_loc_unfrag_tpdu] > 200)
2392            {
2393                *max_frag_size = ((unsigned32)
2394                    (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_loc_unfrag_tpdu])
2395                     - 200) * 1024;
2396            }
2397            else
2398            {
2399                *max_frag_size = ((unsigned32)
2400                    (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_loc_unfrag_tpdu])) * 32;
2401            }
2402            break;
2403        }
2404#endif
2405        return;
2406    }
2407
2408    flag = rpc__ip_is_local_network (rpc_addr, &lstatus);
2409    if (lstatus == rpc_s_ok && flag)
2410    {
2411        *max_frag_size = RPC_C_IP_UDP_MAX_PATH_FRAG_SIZE;
2412#ifdef DEBUG
2413        switch (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_pth_unfrag_tpdu])
2414        {
2415        case 0:
2416            break;
2417        case 1:
2418            *max_frag_size = RPC_C_IP_UDP_MAX_LOC_UNFRG_TPDU;
2419            break;
2420        case 2:
2421            *max_frag_size = RPC_C_FDDI_MAX_DATA_SIZE -
2422                (RPC_C_IP_LLC_SIZE + RPC_C_IP_HDR_SIZE +
2423                 RPC_C_IP_OPTS_SIZE + RPC_C_UDP_HDR_SIZE);
2424            break;
2425        case 3:
2426            *max_frag_size = 4608 -
2427                (RPC_C_IP_LLC_SIZE + RPC_C_IP_HDR_SIZE +
2428                 RPC_C_IP_OPTS_SIZE + RPC_C_UDP_HDR_SIZE);
2429            break;
2430        default:
2431            if (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_pth_unfrag_tpdu] > 200)
2432            {
2433                *max_frag_size = ((unsigned32)
2434                    (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_pth_unfrag_tpdu])
2435                     - 200) * 1024;
2436            }
2437            else
2438            {
2439                *max_frag_size = ((unsigned32)
2440                    (rpc_g_dbg_switches[(int) rpc_es_dbg_ip_max_pth_unfrag_tpdu])) * 32;
2441            }
2442            break;
2443        }
2444#endif
2445        return;
2446    }
2447
2448    *max_frag_size = RPC_C_IP_UDP_MAX_LOC_UNFRG_TPDU;
2449    return;
2450
2451}
2452