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_bsd
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  This module contains routines specific to the Internet Protocol,
90**  the Internet Network Address Family extension service, and the
91**  Berkeley Unix system.
92**
93**
94*/
95
96#include <commonp.h>
97#include <com.h>
98#include <comnaf.h>
99#include <comsoc.h>
100#include <ipnaf.h>
101
102#include <net/if.h>
103#include <sys/ioctl.h>
104
105
106/***********************************************************************
107 *
108 *  Internal prototypes and typedefs.
109 */
110
111typedef boolean (*enumerate_fn_p_t) ((
112        int                     /* in  */  /*desc*/,
113        struct ifreq            /* in  */ * /*ifr*/,
114        unsigned32              /* in  */  /*if_flags*/,
115        struct sockaddr         /* in  */ * /*if_addr*/,
116        rpc_ip_addr_p_t         /* out */  /*ip_addr*/,
117        rpc_ip_addr_p_t         /* out */  /*netmask_addr*/
118    );
119
120INTERNAL void enumerate_interfaces (
121        rpc_protseq_id_t         /*protseq_id*/,
122        rpc_socket_t             /*desc*/,
123        enumerate_fn_p_t         /*efun*/,
124        rpc_addr_vector_p_t     * /*rpc_addr_vec*/,
125        rpc_addr_vector_p_t     * /*netmask_addr_vec*/,
126        unsigned32              * /*st*/
127    );
128
129INTERNAL boolean get_addr (
130        int                      /*desc*/,
131        struct ifreq            * /*ifr*/,
132        unsigned32               /*if_flags*/,
133        struct sockaddr         * /*if_addr*/,
134        rpc_ip_addr_p_t          /*ip_addr*/,
135        rpc_ip_addr_p_t          /*netmask_addr*/
136    );
137
138INTERNAL boolean get_broadcast_addr (
139        int                      /*desc*/,
140        struct ifreq            * /*ifr*/,
141        unsigned32               /*if_flags*/,
142        struct sockaddr         * /*if_addr*/,
143        rpc_ip_addr_p_t          /*ip_addr*/,
144        rpc_ip_addr_p_t          /*netmask_addr*/
145    );
146
147#ifndef NO_SPRINTF
148#  define RPC__IP_NETWORK_SPRINTF   sprintf
149#else
150#  define RPC__IP_NETWORK_SPRINTF   rpc__ip_network_sprintf
151#endif
152
153typedef struct
154{
155    unsigned32  num_elt;
156    struct
157    {
158        unsigned32  addr;
159        unsigned32  netmask;
160    } elt[1];
161} rpc_ip_s_addr_vector_t, *rpc_ip_s_addr_vector_p_t;
162
163INTERNAL rpc_ip_s_addr_vector_p_t local_ip_addr_vec = NULL;
164
165/*
166**++
167**
168**  ROUTINE NAME:       enumerate_interfaces
169**
170**  SCOPE:              INTERNAL - declared locally
171**
172**  DESCRIPTION:
173**
174**  Return a vector of IP RPC addresses.  Note that this function is
175**  shared by both "rpc__ip_desc_inq_addr" and "rpc__ip_get_broadcast"
176**  so that we have to have only one copy of all the gore (ioctl's)
177**  associated with inquiring about network interfaces.  This routine
178**  filters out all network interface information that doesn't correspond
179**  to up, non-loopback, IP-addressed network interfaces.  The supplied
180**  procedure pointer (efun) does the rest of the work.
181**
182**
183**  INPUTS:
184**
185**      protseq_id      Protocol Sequence ID representing a particular
186**                      Network Address Family, its Transport Protocol,
187**                      and type.
188**
189**      desc            Descriptor, indicating a socket that has been
190**                      created on the local operating platform.
191**
192**      efun            Procedure pointer supplied to "do the rest of the work".
193**
194**  INPUTS/OUTPUTS:     none
195**
196**  OUTPUTS:
197**
198**      rpc_addr_vec    Returned vector of RPC addresses.
199**
200**      netmask_addr_vec Returned vector of netmask RPC addresses.
201**
202**      status          A value indicating the status of the routine.
203**
204**  IMPLICIT INPUTS:    none
205**
206**  IMPLICIT OUTPUTS:   none
207**
208**  FUNCTION VALUE:     none
209**
210**  SIDE EFFECTS:       none
211**
212**--
213**/
214
215#ifdef _SOCKADDR_LEN
216/*
217 * Note that in the world of BSD 4.4, the struct ifreq's returned
218 * from SIOCGIFCONF are *varying length*, but a minimum of 32 bytes.
219 *
220 * This has some interesting implications on how to parse the result
221 * from SIOCGIFCONF.
222 */
223#endif
224
225INTERNAL void enumerate_interfaces
226(
227    rpc_protseq_id_t        protseq_id,
228    rpc_socket_t            desc,
229    enumerate_fn_p_t        efun,
230    rpc_addr_vector_p_t     *rpc_addr_vec,
231    rpc_addr_vector_p_t     *netmask_addr_vec,
232    unsigned32              *status
233)
234{
235    rpc_ip_addr_p_t         ip_addr;
236    int                     n_ifs;
237    unsigned char           buf[1024];
238    struct ifconf           ifc;
239    struct ifreq            *ifr, *last_ifr;
240    struct ifreq            ifreq;
241    short                   if_flags;
242    struct sockaddr         if_addr;
243    int                     i;
244#ifdef _SOCKADDR_LEN
245    int                     prev_size;
246#else
247    const int prev_size = sizeof(struct ifreq) ;
248#endif
249    rpc_ip_addr_p_t         netmask_addr = NULL;
250
251    CODING_ERROR (status);
252
253    /*
254     * Get the list of network interfaces.
255     */
256    ifc.ifc_len = sizeof (buf);
257    ifc.ifc_buf = (caddr_t) buf;
258
259ifconf_again:
260    if (ioctl (desc, (int) SIOCGIFCONF, (caddr_t) &ifc) < 0)
261    {
262        if (errno == EINTR)
263        {
264            goto ifconf_again;
265        }
266        *status = -2;   /* !!! */
267        return;
268    }
269
270    /*
271     * Figure out how many interfaces there must be and allocate an
272     * RPC address vector with the appropriate number of elements.
273     * (We may ask for a few too many in case some of the interfaces
274     * are uninteresting.)
275     */
276    n_ifs = ifc.ifc_len / sizeof (struct ifreq);
277    RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
278        ("%d bytes of ifreqs, ifreq is %d bytes\n", ifc.ifc_len, sizeof(struct ifreq)));
279
280#ifdef MAX_DEBUG
281    if (RPC_DBG2(rpc_e_dbg_general, 15))
282    {
283        int i;
284	char msgbuf[128];
285
286        for (i=0; i<ifc.ifc_len; i++) {
287            if ((i % 32) == 0) {
288		if (i != 0)
289		    RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf));
290                sprintf(msgbuf, "%4x: ", i);
291	    }
292            sprintf(msgbuf, "%s%02x ", msgbuf, buf[i]);
293        }
294	if (i != 0)
295	    RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf));
296    }
297#endif
298
299    RPC_MEM_ALLOC (
300        *rpc_addr_vec,
301        rpc_addr_vector_p_t,
302        (sizeof **rpc_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))),
303        RPC_C_MEM_RPC_ADDR_VEC,
304        RPC_C_MEM_WAITOK);
305
306    if (*rpc_addr_vec == NULL)
307    {
308        *status = rpc_s_no_memory;
309        return;
310    }
311    if (netmask_addr_vec != NULL)
312    {
313        RPC_MEM_ALLOC (
314            *netmask_addr_vec,
315            rpc_addr_vector_p_t,
316         (sizeof **netmask_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))),
317            RPC_C_MEM_RPC_ADDR_VEC,
318            RPC_C_MEM_WAITOK);
319
320        if (*netmask_addr_vec == NULL)
321        {
322            *status = rpc_s_no_memory;
323            RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
324            return;
325        }
326
327        (*netmask_addr_vec)->len = 0;
328    }
329
330    /*
331     * Go through the interfaces and get the info associated with them.
332     */
333    (*rpc_addr_vec)->len = 0;
334    last_ifr = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
335
336    for (i=0, ifr = ifc.ifc_req; ifr < last_ifr ;
337         i++, ifr = (struct ifreq *)(( (char *) ifr ) + prev_size))
338    {
339#ifdef _SOCKADDR_LEN
340        prev_size = sizeof (struct ifreq) - sizeof(struct sockaddr) + ifr->ifr_addr.sa_len ;
341#endif
342        RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("interface %d: %s\n",
343            i, ifr->ifr_name));
344        /*
345         * Get the interface's flags.  If the flags say that the interface
346         * is not up or is the loopback interface, skip it.  Do the
347         * SIOCGIFFLAGS on a copy of the ifr so we don't lose the original
348         * contents of the ifr.  (ifr's are unions that hold only one
349         * of the interesting interface attributes [address, flags, etc.]
350         * at a time.)
351         */
352        memcpy(&ifreq, ifr, sizeof(ifreq));
353ifflags_again:
354        if (ioctl(desc, SIOCGIFFLAGS, &ifreq) < 0)
355        {
356            RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
357                ("SIOCGIFFLAGS returned errno %d\n", errno));
358            if (errno == EINTR)
359            {
360                goto ifflags_again;
361            }
362            continue;
363        }
364        if_flags = ifreq.ifr_flags;     /* Copy out the flags */
365        RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("flags are %x\n", if_flags));
366
367        /*
368         * Ignore interfaces which are not 'up'.
369         */
370        if ((if_flags & IFF_UP) == 0)
371            continue;
372
373        /*
374         * Get the addressing stuff for this interface.
375         */
376
377#ifdef NO_SIOCGIFADDR
378
379        /*
380         * Note that some systems do not return the address for the
381         * interface given.  However the ifr array elts contained in
382         * the ifc block returned from the SIOCGIFCONF ioctl above already
383         * contains the correct addresses. So these systems should define
384         * NO_SIOCGIFADDR in their platform specific include file.
385         */
386        if_addr = ifr->ifr_addr;
387
388#else
389
390        /*
391         * Do the SIOCGIFADDR on a copy of the ifr.  See above.
392         */
393        memcpy(&ifreq, ifr, sizeof(ifreq));
394ifaddr_again:
395        if (ioctl(desc, SIOCGIFADDR, &ifreq) < 0)
396        {
397            RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
398                ("SIOCGIFADDR returned errno %d\n", errno));
399            if (errno == EINTR)
400            {
401                goto ifaddr_again;
402            }
403
404            *status = -4;
405            goto FREE_IT;
406        }
407
408        memcpy (&if_addr, &ifr->ifr_addr, sizeof(struct sockaddr));
409
410#endif  /* NO_SIOCGIFADDR */
411
412        /*
413         * If this isn't an Internet-family address, ignore it.
414         */
415        if (if_addr.sa_family != AF_INET)
416        {
417            RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("AF %d not INET\n",
418                if_addr.sa_family));
419            continue;
420        }
421
422        /*
423         * Allocate and fill in an IP RPC address for this interface.
424         */
425        RPC_MEM_ALLOC (
426            ip_addr,
427            rpc_ip_addr_p_t,
428            sizeof (rpc_ip_addr_t),
429            RPC_C_MEM_RPC_ADDR,
430            RPC_C_MEM_WAITOK);
431
432        if (ip_addr == NULL)
433        {
434            *status = rpc_s_no_memory;
435            goto FREE_IT;
436        }
437
438        ip_addr->rpc_protseq_id = protseq_id;
439        ip_addr->len            = sizeof (struct sockaddr_in);
440        if (netmask_addr_vec != NULL)
441        {
442            RPC_MEM_ALLOC (
443                netmask_addr,
444                rpc_ip_addr_p_t,
445                sizeof (rpc_ip_addr_t),
446                RPC_C_MEM_RPC_ADDR,
447                RPC_C_MEM_WAITOK);
448
449            if (netmask_addr == NULL)
450            {
451                *status = rpc_s_no_memory;
452                RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR);
453                goto FREE_IT;
454            }
455
456            netmask_addr->rpc_protseq_id = protseq_id;
457            netmask_addr->len            = sizeof (struct sockaddr_in);
458        }
459
460        /*
461         * Call out to do any final filtering and get the desired IP address
462         * for this interface.  If the callout function returns false, we
463         * forget about this interface.
464         */
465        if ((*efun) (desc, ifr, if_flags, &if_addr, ip_addr, netmask_addr) == false)
466        {
467            RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR);
468            if (netmask_addr != NULL)
469                RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR);
470            continue;
471        }
472
473        RPC_SOCKET_FIX_ADDRLEN(ip_addr);
474        (*rpc_addr_vec)->addrs[(*rpc_addr_vec)->len++] = (rpc_addr_p_t) ip_addr;
475        if (netmask_addr_vec != NULL && netmask_addr != NULL)
476            (*netmask_addr_vec)->addrs[(*netmask_addr_vec)->len++]
477                = (rpc_addr_p_t) netmask_addr;
478    }
479
480    if ((*rpc_addr_vec)->len == 0)
481    {
482        *status = -5;   /* !!! */
483        goto FREE_IT;
484    }
485
486    *status = rpc_s_ok;
487    return;
488
489FREE_IT:
490
491    for (i = 0; i < (*rpc_addr_vec)->len; i++)
492    {
493        RPC_MEM_FREE ((*rpc_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR);
494    }
495
496    RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
497    if (netmask_addr_vec != NULL)
498    {
499        for (i = 0; i < (*netmask_addr_vec)->len; i++)
500        {
501            RPC_MEM_FREE ((*netmask_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR);
502        }
503        RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
504    }
505}
506
507/*
508**++
509**
510**  ROUTINE NAME:       get_addr
511**
512**  SCOPE:              INTERNAL - declared locally
513**
514**  DESCRIPTION:
515**
516**  This function is called from "rpc__ip_desc_inq_addr" via
517**  "enumerate_interfaces".  See comments in "enumerate_interfaces" for
518**  details.
519**
520**
521**  INPUTS:             none
522**
523**      desc            Socket being used for ioctl's.
524**
525**      ifr             Structure describing the interface.
526**
527**  INPUTS/OUTPUTS:     none
528**
529**  OUTPUTS:
530**
531**      ip_addr
532**
533**      netmask_addr    netmask address
534**
535**  IMPLICIT INPUTS:    none
536**
537**  IMPLICIT OUTPUTS:   none
538**
539**  FUNCTION VALUE:
540**
541**      result          true => we generated up an address for this interface
542**                      false => we didn't.
543**
544**  SIDE EFFECTS:       none
545**
546**--
547**/
548
549INTERNAL boolean get_addr
550(
551    int                     desc,
552    struct ifreq            *ifr,
553    unsigned32              if_flags,
554    struct sockaddr         *if_addr,
555    rpc_ip_addr_p_t         ip_addr,
556    rpc_ip_addr_p_t         netmask_addr
557)
558{
559    struct ifreq            ifreq;
560
561    if (netmask_addr == NULL)
562    {
563        if ((if_flags & IFF_LOOPBACK) != 0)
564        {
565            return (false);
566        }
567
568        memcpy (&ip_addr->sa, if_addr, sizeof(struct sockaddr_in));
569        return (true);
570    }
571    else
572    {
573        memcpy (&ip_addr->sa, if_addr, sizeof(struct sockaddr_in));
574
575        /*
576         * Inquire the interface's netmask address.
577         */
578        ifreq = *ifr;
579    ifnetaddr_again:
580        if (ioctl(desc, (int) SIOCGIFNETMASK, &ifreq) == -1)
581        {
582            if (errno == EINTR)
583            {
584                goto ifnetaddr_again;
585            }
586
587            return (false);
588        }
589
590        memcpy (&netmask_addr->sa, &ifreq.ifr_addr, sizeof(struct sockaddr_in));
591        return (true);
592    }
593}
594
595/*
596**++
597**
598**  ROUTINE NAME:       rpc__ip_desc_inq_addr
599**
600**  SCOPE:              PRIVATE - declared in ipnaf.h
601**
602**  DESCRIPTION:
603**
604**  Receive a socket descriptor which is queried to obtain family, endpoint
605**  and network address.  If this information appears valid for an IP
606**  address,  space is allocated for an RPC address which is initialized
607**  with the information obtained from the socket.  The address indicating
608**  the created RPC address is returned in rpc_addr.
609**
610**  INPUTS:
611**
612**      protseq_id      Protocol Sequence ID representing a particular
613**                      Network Address Family, its Transport Protocol,
614**                      and type.
615**
616**      desc            Descriptor, indicating a socket that has been
617**                      created on the local operating platform.
618**
619**  INPUTS/OUTPUTS:     none
620**
621**  OUTPUTS:
622**
623**      rpc_addr_vec
624**
625**      status          A value indicating the status of the routine.
626**
627**          rpc_s_ok               The call was successful.
628**
629**          rpc_s_no_memory         Call to malloc failed to allocate memory.
630**
631**          rpc_s_cant_inq_socket  Attempt to get info about socket failed.
632**
633**          Any of the RPC Protocol Service status codes.
634**
635**  IMPLICIT INPUTS:    none
636**
637**  IMPLICIT OUTPUTS:   none
638**
639**  FUNCTION VALUE:     none
640**
641**  SIDE EFFECTS:       none
642**
643**--
644**/
645
646PRIVATE void rpc__ip_desc_inq_addr
647(
648    rpc_protseq_id_t        protseq_id,
649    rpc_socket_t            desc,
650    rpc_addr_vector_p_t     *rpc_addr_vec,
651    unsigned32              *status
652)
653{
654    rpc_ip_addr_p_t         ip_addr;
655    rpc_ip_addr_t           loc_ip_addr;
656    unsigned16              i;
657
658    CODING_ERROR (status);
659
660    /*
661     * Do a "getsockname" into a local IP RPC address.  If the network
662     * address part of the result is non-zero, then the socket must be
663     * bound to a particular IP address and we can just return a RPC
664     * address vector with that one address (and endpoint) in it.
665     * Otherwise, we have to enumerate over all the local network
666     * interfaces the local host has and construct an RPC address for
667     * each one of them.
668     */
669    loc_ip_addr.len = sizeof (rpc_ip_addr_t);
670    RPC_SOCKET_FIX_ADDRLEN(&loc_ip_addr);
671
672    if (getsockname (desc, (struct sockaddr *)&loc_ip_addr.sa, (int *)&loc_ip_addr.len) < 0)
673    {
674        *status = -1;   /* !!! */
675        return;
676    }
677
678    RPC_SOCKET_FIX_ADDRLEN(&loc_ip_addr);
679
680    if (loc_ip_addr.sa.sin_addr.s_addr == 0)
681    {
682        enumerate_interfaces
683            (protseq_id, desc, get_addr, rpc_addr_vec, NULL, status);
684
685        if (*status != rpc_s_ok)
686        {
687            return;
688        }
689        for (i = 0; i < (*rpc_addr_vec)->len; i++)
690        {
691            ((rpc_ip_addr_p_t) (*rpc_addr_vec)->addrs[i])->sa.sin_port = loc_ip_addr.sa.sin_port;
692        }
693    }
694    else
695    {
696        RPC_MEM_ALLOC (
697            ip_addr,
698            rpc_ip_addr_p_t,
699            sizeof (rpc_ip_addr_t),
700            RPC_C_MEM_RPC_ADDR,
701            RPC_C_MEM_WAITOK);
702
703        if (ip_addr == NULL)
704        {
705            *status = rpc_s_no_memory;
706            return;
707        }
708
709        RPC_MEM_ALLOC (
710            *rpc_addr_vec,
711            rpc_addr_vector_p_t,
712            sizeof **rpc_addr_vec,
713            RPC_C_MEM_RPC_ADDR_VEC,
714            RPC_C_MEM_WAITOK);
715
716        if (*rpc_addr_vec == NULL)
717        {
718            RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR);
719            *status = rpc_s_no_memory;
720            return;
721        }
722
723        ip_addr->rpc_protseq_id = protseq_id;
724        ip_addr->len            = sizeof (struct sockaddr_in);
725        ip_addr->sa             = loc_ip_addr.sa;
726
727        (*rpc_addr_vec)->len = 1;
728        (*rpc_addr_vec)->addrs[0] = (rpc_addr_p_t) ip_addr;
729
730        *status = rpc_s_ok;
731        return;
732    }
733}
734
735/*
736**++
737**
738**  ROUTINE NAME:       get_broadcast_addr
739**
740**  SCOPE:              INTERNAL - declared locally
741**
742**  DESCRIPTION:
743**
744**  This function is called from "rpc__ip_get_broadcast" via
745**  "enumerate_interfaces".  See comments in "enumerate_interfaces" for
746**  details.
747**
748**
749**  INPUTS:             none
750**
751**      desc            Socket being used for ioctl's.
752**
753**      ifr             Structure describing the interface.
754**
755**  INPUTS/OUTPUTS:     none
756**
757**  OUTPUTS:
758**
759**      ip_addr
760**
761**  IMPLICIT INPUTS:    none
762**
763**  IMPLICIT OUTPUTS:   none
764**
765**  FUNCTION VALUE:     none
766**
767**      result          true => we generated up an address for this interface
768**                      false => we didn't.
769**
770**  SIDE EFFECTS:       none
771**
772**--
773**/
774
775INTERNAL boolean get_broadcast_addr
776(
777    int                     desc,
778    struct ifreq            *ifr,
779    unsigned32              if_flags,
780    struct sockaddr         *if_addr,
781    rpc_ip_addr_p_t         ip_addr,
782    rpc_ip_addr_p_t         netmask_addr
783)
784{
785    struct ifreq            ifreq;
786
787    /*
788     * If the interface's flags say this isn't a broadcast interface,
789     * or isn't up, ignore it.
790     */
791    if ((if_flags & IFF_BROADCAST) == 0 || (if_flags & IFF_UP) == 0)
792    {
793        return (false);
794    }
795
796#ifndef BROADCAST_NEEDS_LOOPBACK
797    /*
798     * #define BROADCAST_NEEDS_LOOPBACK in case you need to broadcast
799     * over the loopback interface to see your own broadcasts.
800     */
801    if ((if_flags & IFF_LOOPBACK) != 0)
802    {
803        return (false);
804    }
805#endif
806
807    /*
808     * Inquire the interface's broadcast address.
809     */
810    ifreq = *ifr;
811    ifbrdaddr_again:
812    if (ioctl(desc, (int) SIOCGIFBRDADDR, &ifreq) < 0)
813    {
814        if (errno == EINTR)
815        {
816            goto ifbrdaddr_again;
817        }
818
819        return (false);
820    }
821
822    memcpy (&ip_addr->sa, &ifreq.ifr_broadaddr, sizeof(struct sockaddr_in));
823    RPC_SOCKET_FIX_ADDRLEN(ip_addr);
824    return (true);
825}
826
827/*
828**++
829**
830**  ROUTINE NAME:       rpc__ip_get_broadcast
831**
832**  SCOPE:              PRIVATE - EPV declared in ipnaf.h
833**
834**  DESCRIPTION:
835**
836**  Return a vector of RPC addresses that represent all the address
837**  required so that sending on all of them results in broadcasting on
838**  all the local network interfaces.
839**
840**
841**  INPUTS:
842**
843**      naf_id          Network Address Family ID serves
844**                      as index into EPV for IP routines.
845**
846**      rpc_protseq_id
847**
848**  INPUTS/OUTPUTS:     none
849**
850**  OUTPUTS:
851**
852**      rpc_addr_vec
853**
854**      status          A value indicating the status of the routine.
855**
856**  IMPLICIT INPUTS:    none
857**
858**  IMPLICIT OUTPUTS:   none
859**
860**  FUNCTION VALUE:     none
861**
862**  SIDE EFFECTS:       none
863**
864**--
865**/
866
867PRIVATE void rpc__ip_get_broadcast
868(
869    rpc_naf_id_t            naf_id,
870    rpc_protseq_id_t        protseq_id,
871    rpc_addr_vector_p_t     *rpc_addr_vec,
872    unsigned32              *status
873)
874{
875    int                     desc;
876
877    CODING_ERROR (status);
878
879    /*
880     * Open a socket to pass to "enumerate_interface".
881     */
882    desc = socket(AF_INET, SOCK_DGRAM, 0);
883
884    if (desc < 0)
885    {
886        *status = -7;   /* !!! */
887        return;
888    }
889
890    enumerate_interfaces
891        (protseq_id, desc, get_broadcast_addr, rpc_addr_vec, NULL, status);
892    close(desc);
893}
894
895/*
896**++
897**
898**  ROUTINE NAME:       rpc__ip_init_local_addr_vec
899**
900**  SCOPE:              PRIVATE - declared in ipnaf.h
901**
902**  DESCRIPTION:
903**
904**  Initialize the local address vectors.
905**
906**
907**  INPUTS:             none
908**
909**  INPUTS/OUTPUTS:     none
910**
911**  OUTPUTS:
912**
913**      status          A value indicating the status of the routine.
914**
915**  IMPLICIT INPUTS:    none
916**
917**  IMPLICIT OUTPUTS:   none
918**
919**  FUNCTION VALUE:     none
920**
921**  SIDE EFFECTS:
922**
923**      Update local_ip_addr_vec
924**
925**--
926**/
927
928PRIVATE void rpc__ip_init_local_addr_vec
929(
930    unsigned32 *status
931)
932{
933    int                     desc;
934    unsigned32              lstatus;
935    unsigned32              i;
936    rpc_addr_vector_p_t     rpc_addr_vec = NULL;
937    rpc_addr_vector_p_t     netmask_addr_vec = NULL;
938
939    CODING_ERROR (status);
940
941    /*
942     * Open a socket to pass to "enumerate_interface".
943     */
944    desc = socket(AF_INET, SOCK_DGRAM, 0);
945
946    if (desc < 0)
947    {
948        *status = rpc_s_cant_create_socket;   /* !!! */
949        return;
950    }
951
952    enumerate_interfaces
953        (rpc_c_protseq_id_ncadg_ip_udp, desc, get_addr,
954         &rpc_addr_vec, &netmask_addr_vec, status);
955    close(desc);
956
957    if (*status != rpc_s_ok)
958    {
959        return;
960    }
961
962    /*
963     * Do some sanity check.
964     */
965
966    if (rpc_addr_vec == NULL
967        || netmask_addr_vec == NULL
968        || rpc_addr_vec->len != netmask_addr_vec->len
969        || rpc_addr_vec->len == 0)
970    {
971        RPC_DBG_GPRINTF(("(rpc__ip_init_local_addr_vec) no local address\n"));
972        *status = rpc_s_no_addrs;
973        goto free_rpc_addrs;
974    }
975
976    RPC_MEM_ALLOC (
977        local_ip_addr_vec,
978        rpc_ip_s_addr_vector_p_t,
979        (sizeof *local_ip_addr_vec)
980            + ((rpc_addr_vec->len - 1) * (sizeof (local_ip_addr_vec->elt[0]))),
981        RPC_C_MEM_UTIL,
982        RPC_C_MEM_WAITOK);
983    if (local_ip_addr_vec == NULL)
984    {
985        *status = rpc_s_no_memory;
986        goto free_rpc_addrs;
987    }
988
989    local_ip_addr_vec->num_elt = rpc_addr_vec->len;
990
991    for (i = 0; i < rpc_addr_vec->len; i++)
992    {
993        local_ip_addr_vec->elt[i].addr =
994            ((rpc_ip_addr_p_t) rpc_addr_vec->addrs[i])->sa.sin_addr.s_addr;
995        local_ip_addr_vec->elt[i].netmask =
996            ((rpc_ip_addr_p_t) netmask_addr_vec->addrs[i])->sa.sin_addr.s_addr;
997#ifdef DEBUG
998        if (RPC_DBG2(rpc_e_dbg_general, 10))
999        {
1000            char         buff[16], mbuff[16];
1001            unsigned8    *p, *mp;
1002
1003            p = (unsigned8 *) &(local_ip_addr_vec->elt[i].addr);
1004            mp = (unsigned8 *) &(local_ip_addr_vec->elt[i].netmask);
1005            RPC__IP_NETWORK_SPRINTF(buff, "%d.%d.%d.%d",
1006                                    UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
1007            RPC__IP_NETWORK_SPRINTF(mbuff, "%d.%d.%d.%d",
1008                                    UC(mp[0]), UC(mp[1]), UC(mp[2]), UC(mp[3]));
1009            RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
1010            ("(rpc__ip_init_local_addr_vec) local network [%s] netmask [%s]\n",
1011                            buff, mbuff));
1012        }
1013#endif
1014    }
1015
1016free_rpc_addrs:
1017    if (rpc_addr_vec != NULL)
1018    {
1019        for (i = 0; i < rpc_addr_vec->len; i++)
1020        {
1021            RPC_MEM_FREE (rpc_addr_vec->addrs[i], RPC_C_MEM_RPC_ADDR);
1022        }
1023        RPC_MEM_FREE (rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
1024    }
1025    if (netmask_addr_vec != NULL)
1026    {
1027        for (i = 0; i < netmask_addr_vec->len; i++)
1028        {
1029            RPC_MEM_FREE (netmask_addr_vec->addrs[i], RPC_C_MEM_RPC_ADDR);
1030        }
1031        RPC_MEM_FREE (netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
1032    }
1033    return;
1034}
1035
1036/*
1037**++
1038**
1039**  ROUTINE NAME:       rpc__ip_is_local_network
1040**
1041**  SCOPE:              PRIVATE - declared in ipnaf.h
1042**
1043**  DESCRIPTION:
1044**
1045**  Return a boolean value to indicate if the given RPC address is on
1046**  the same IP subnet.
1047**
1048**
1049**  INPUTS:
1050**
1051**      rpc_addr        The address that forms the path of interest
1052**
1053**  INPUTS/OUTPUTS:     none
1054**
1055**  OUTPUTS:
1056**
1057**      status          A value indicating the status of the routine.
1058**
1059**  IMPLICIT INPUTS:    none
1060**
1061**  IMPLICIT OUTPUTS:   none
1062**
1063**  FUNCTION VALUE:
1064**
1065**      result          true => the address is on the same subnet.
1066**                      false => not.
1067**
1068**  SIDE EFFECTS:       none
1069**
1070**--
1071**/
1072PRIVATE boolean32 rpc__ip_is_local_network
1073(
1074    rpc_addr_p_t rpc_addr,
1075    unsigned32   *status
1076)
1077{
1078    rpc_ip_addr_p_t         ip_addr = (rpc_ip_addr_p_t) rpc_addr;
1079    unsigned32              addr1;
1080    unsigned32              addr2;
1081    unsigned32              i;
1082
1083    CODING_ERROR (status);
1084
1085    if (rpc_addr == NULL)
1086    {
1087        *status = rpc_s_invalid_arg;
1088        return false;
1089    }
1090
1091    *status = rpc_s_ok;
1092
1093    if (local_ip_addr_vec == NULL)
1094    {
1095        /*
1096         * We should call rpc__ip_init_local_addr_vec() here. But, it
1097         * requires the mutex lock for local_ip_addr_vec. For now just return
1098         * false.
1099         */
1100        return false;
1101    }
1102
1103    /*
1104     * Compare addresses.
1105     */
1106    for (i = 0; i < local_ip_addr_vec->num_elt; i++)
1107    {
1108        if (ip_addr->sa.sin_family != AF_INET)
1109        {
1110            continue;
1111        }
1112
1113        addr1 = ip_addr->sa.sin_addr.s_addr & local_ip_addr_vec->elt[i].netmask;
1114        addr2 = local_ip_addr_vec->elt[i].addr & local_ip_addr_vec->elt[i].netmask;
1115
1116        if (addr1 == addr2)
1117        {
1118            return true;
1119        }
1120    }
1121
1122    return false;
1123}
1124
1125/*
1126**++
1127**
1128**  ROUTINE NAME:       rpc__ip_is_local_addr
1129**
1130**  SCOPE:              PRIVATE - declared in ipnaf.h
1131**
1132**  DESCRIPTION:
1133**
1134**  Return a boolean value to indicate if the given RPC address is the
1135**  the local IP address.
1136**
1137**
1138**  INPUTS:
1139**
1140**      rpc_addr        The address that forms the path of interest
1141**
1142**  INPUTS/OUTPUTS:     none
1143**
1144**  OUTPUTS:
1145**
1146**      status          A value indicating the status of the routine.
1147**
1148**  IMPLICIT INPUTS:    none
1149**
1150**  IMPLICIT OUTPUTS:   none
1151**
1152**  FUNCTION VALUE:
1153**
1154**      result          true => the address is local.
1155**                      false => not.
1156**
1157**  SIDE EFFECTS:       none
1158**
1159**--
1160**/
1161
1162PRIVATE boolean32 rpc__ip_is_local_addr
1163(
1164    rpc_addr_p_t rpc_addr,
1165    unsigned32   *status
1166)
1167{
1168    rpc_ip_addr_p_t         ip_addr = (rpc_ip_addr_p_t) rpc_addr;
1169    unsigned32              i;
1170
1171    CODING_ERROR (status);
1172
1173    if (rpc_addr == NULL)
1174    {
1175        *status = rpc_s_invalid_arg;
1176        return false;
1177    }
1178
1179    *status = rpc_s_ok;
1180
1181    if (local_ip_addr_vec == NULL)
1182    {
1183        /*
1184         * We should call rpc__ip_init_local_addr_vec() here. But, it
1185         * requires the mutex lock for local_ip_addr_vec. For now just return
1186         * false.
1187         */
1188        return false;
1189    }
1190
1191    /*
1192     * Compare addresses.
1193     */
1194    for (i = 0; i < local_ip_addr_vec->num_elt; i++)
1195    {
1196        if (ip_addr->sa.sin_family != AF_INET)
1197        {
1198            continue;
1199        }
1200
1201        if (ip_addr->sa.sin_addr.s_addr == local_ip_addr_vec->elt[i].addr)
1202        {
1203            return true;
1204        }
1205    }
1206
1207    return false;
1208}
1209