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**      comsoc.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  Veneer over the BSD socket abstraction not provided by the old sock_
90**  or new rpc_{tower,addr}_ components.
91**
92**
93*/
94
95#include <config.h>
96#include <dce/lrpc.h>
97#include <commonp.h>
98#include <com.h>
99#include <comprot.h>
100#include <comnaf.h>
101#include <comp.h>
102#include <comsoc_bsd.h>
103#include <fcntl.h>
104#include <sys/un.h>
105#include <sys/types.h>
106#include <sys/stat.h>
107#include <sys/param.h>
108#include <sys/socket.h>
109#include <cnp.h>
110
111#if HAVE_LW_BASE_H
112#include <lw/base.h>
113#endif
114
115#if HAVE_LWMAPSECURITY_LWMAPSECURITY_H
116#include <lwmapsecurity/lwmapsecurity.h>
117#endif
118
119/* Bizarre hack for HP-UX ia64 where a system header
120 * makes reference to a kernel-only data structure
121 */
122#if defined(__hpux) && defined(__ia64)
123union mpinfou {};
124#endif
125#include <net/if.h>
126#include <sys/ioctl.h>
127/* Hack to ensure we actually get a definition of ioctl on AIX */
128#if defined(_AIX) && defined(_BSD)
129int ioctl(int d, int request, ...);
130#endif
131#include <unistd.h>
132#ifdef HAVE_SYS_SOCKIO_H
133#include <sys/sockio.h> /* Not just Linux */
134#endif
135
136/*#include <dce/cma_ux_wrappers.h>*/
137
138/* ======================================================================== */
139
140/*
141 * What we think a socket's buffering is in case rpc__socket_set_bufs()
142 * fails miserably.  The #ifndef is here so that these values can be
143 * overridden in a per-system file.
144 */
145
146#ifndef RPC_C_SOCKET_GUESSED_RCVBUF
147#  define RPC_C_SOCKET_GUESSED_RCVBUF    (4 * 1024)
148#endif
149
150#ifndef RPC_C_SOCKET_GUESSED_SNDBUF
151#  define RPC_C_SOCKET_GUESSED_SNDBUF    (4 * 1024)
152#endif
153
154/*
155 * Maximum send and receive buffer sizes.  The #ifndef is here so that
156 * these values can be overridden in a per-system file.
157 */
158
159#ifndef RPC_C_SOCKET_MAX_RCVBUF
160#  define RPC_C_SOCKET_MAX_RCVBUF (64 * 1024)
161#endif
162
163#ifndef RPC_C_SOCKET_MAX_SNDBUF
164#  define RPC_C_SOCKET_MAX_SNDBUF (64 * 1024)
165#endif
166
167/*
168 * The RPC_SOCKET_DISABLE_CANCEL/RPC_SOCKET_RESTORE_CANCEL macros
169 * are used to disable cancellation before entering library calls
170 * which were non-cancelable under CMA threads but are generally
171 * cancelable on modern POSIX systems.
172 */
173#define RPC_SOCKET_DISABLE_CANCEL	{ int __cs = dcethread_enableinterrupt_throw(0);
174#define RPC_SOCKET_RESTORE_CANCEL	dcethread_enableinterrupt_throw(__cs); }
175
176/*
177 * Macros to paper over the difference between the 4.4bsd and 4.3bsd
178 * socket API.
179 *
180 * The layout of a 4.4 struct sockaddr includes a 1 byte "length" field
181 * which used to be one of the bytes of the "family" field.  (The "family"
182 * field is now 1 byte instead of 2 bytes.)  4.4 provides binary
183 * compatibility with applications compiled with a 4.3 sockaddr definition
184 * by inferring a default length when the supplied length is zero.  Source
185 * compatibility is blown however (if _SOCKADDR_LEN is #define'd) --
186 * applications that assign only to the "family" field will leave the
187 * "length" field possibly non-zero.
188 *
189 * Note that RPC's "sockaddr_t" is always defined to contains only a
190 * family.  (We defined "rpc_addr_t" to be a struct that contains a length
191 * and a sockaddr rather than mucking with the sockaddr itself.)  We
192 * assumed that "sockaddr_t" and "struct sockaddr" are the same.  At
193 * 4.4, this assumption caused problems.  We use RPC_SOCKET_FIX_ADDRLEN
194 * at various opportunities to make sure sockaddrs' length is zero and
195 * that makes the problems go away.
196 *
197 * ADDENDUM:
198 *    This only makes the problem go away on little-endian systems
199 *    where the length field on the 4.4 struct occupies the same position
200 *    as the high byte of the family field on the 4.3 struct.  This is
201 *    no good for i386 FreeBSD, so we have actually adapted sockaddr_t
202 *    to match the system struct sockaddr.
203 *                                           -- Brian Koropoff, Likewise
204 *
205 * RPC_SOCKET_FIX_ADDRLEN takes an "rpc_addr_p_t" (or "rpc_ip_addr_p_t")
206 * as input.  The complicated casting (as opposed to simply setting
207 * ".sa_len" to zero) is to ensure that the right thing happens regardless
208 * of the integer endian-ness of the system).
209 *
210 * RPC_SOCKET_INIT_MGRHDR deals with the differences in the field names of
211 * the "struct msghdr" data type between 4.3 and 4.4.
212 */
213
214#ifdef BSD_4_4_SOCKET
215#define RPC_SOCKET_INIT_MSGHDR(msgp) ( \
216    (msgp)->msg_control         = NULL, \
217    (msgp)->msg_controllen      = 0, \
218    (msgp)->msg_flags           = 0 \
219)
220#else
221#define RPC_SOCKET_INIT_MSGHDR(msgp) ( \
222    (msgp)->msg_accrights       = NULL, \
223    (msgp)->msg_accrightslen    = 0 \
224)
225#endif /* BSD_4_4_SOCKET */
226
227/*#if defined(_SOCKADDR_LEN)
228#define RPC_SOCKET_FIX_ADDRLEN(addrp) ( \
229      ((struct osockaddr *) &(addrp)->sa)->sa_family = \
230              ((struct sockaddr *) &(addrp)->sa)->sa_family \
231  )
232  #else*/
233#define RPC_SOCKET_FIX_ADDRLEN(addrp) do { } while (0)
234/*#endif*/
235
236#ifndef CMSG_ALIGN
237#if defined(_CMSG_DATA_ALIGN)
238#define CMSG_ALIGN _CMSG_DATA_ALIGN
239
240#elif defined(_CMSG_ALIGN)
241#define CMSG_ALIGN _CMSG_ALIGN
242
243#elif defined(__DARWIN_ALIGN32)
244#define CMSG_ALIGN __DARWIN_ALIGN32
245
246#elif defined(ALIGN)
247#define CMSG_ALIGN ALIGN
248#endif
249#endif /* CMSG_ALIGN */
250
251#ifndef CMSG_SPACE
252#define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
253#endif
254
255#ifndef CMSG_LEN
256#define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
257#endif
258
259/*
260 * BSD socket transport layer info structures
261 */
262typedef struct rpc_bsd_transport_info_s
263{
264    uid_t peer_uid;
265    gid_t peer_gid;
266} rpc_bsd_transport_info_t, *rpc_bsd_transport_info_p_t;
267
268typedef struct rpc_bsd_socket_s
269{
270    int fd;
271    rpc_bsd_transport_info_t info;
272} rpc_bsd_socket_t, *rpc_bsd_socket_p_t;
273
274INTERNAL rpc_socket_error_t
275rpc__bsd_socket_set_default_options (
276                                     rpc_socket_basic_t sockfd)
277{
278#ifdef SO_NOSIGPIPE
279    int on = 1;
280
281    /* Set SO_NOSIGPIPE on the socket */
282    if (setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on)) == -1) {
283        return errno;
284    }
285#endif
286    return RPC_C_SOCKET_OK;
287}
288
289INTERNAL rpc_socket_error_t rpc__bsd_socket_destruct
290(
291    rpc_socket_t        sock
292);
293
294INTERNAL rpc_socket_error_t rpc__bsd_socket_construct(
295    rpc_socket_t                sock,
296    rpc_protseq_id_t            pseq_id,
297    rpc_transport_info_handle_t info
298);
299
300/* ======================================================================== */
301/*
302 * R P C _ _ S O C K E T _ D U P L I C A T E
303 *
304 * Wrap the native socket representation in a rpc_socket_t. We duplicate the
305 * socket file descriptor because we will eventually end up close(2)ing it.
306 */
307
308INTERNAL rpc_socket_error_t
309rpc__bsd_socket_duplicate(
310    rpc_socket_t        sock,
311    rpc_protseq_id_t    pseq_id ATTRIBUTE_UNUSED,
312    const void *        sockrep /* pointer to native representation */
313    )
314{
315    rpc_socket_error_t  serr;
316    rpc_bsd_socket_p_t  lrpc;
317    const int *         sockfd = (const int *)sockrep;
318
319    if (sockfd == NULL || *sockfd == -1) {
320        return RPC_C_SOCKET_ENOTSOCK;
321    }
322
323    if (sock->pseq_id != pseq_id) {
324        return RPC_C_SOCKET_EINVAL;
325    }
326
327    serr = rpc__bsd_socket_destruct(sock);
328    if (serr != RPC_C_SOCKET_OK) {
329        return serr;
330    }
331
332    serr = rpc__bsd_socket_construct(sock, pseq_id, NULL);
333    if (serr != RPC_C_SOCKET_OK) {
334        return serr;
335    }
336
337    lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
338
339    RPC_SOCKET_DISABLE_CANCEL;
340
341    if (lrpc->fd != -1) {
342        close(lrpc->fd);
343    }
344
345    lrpc->fd = dup(*sockfd);
346
347    serr = ((lrpc->fd == -1) ? errno : RPC_C_SOCKET_OK);
348    if (serr != RPC_C_SOCKET_OK) {
349        goto error;
350    }
351
352    serr = rpc__bsd_socket_set_default_options(lrpc->fd);
353    if (serr != RPC_C_SOCKET_OK) {
354        goto error;
355    }
356
357    RPC_SOCKET_RESTORE_CANCEL;
358
359    return RPC_C_SOCKET_OK;
360
361error:
362    rpc__bsd_socket_destruct(sock);
363    return serr;
364}
365
366/*
367 * R P C _ _ S O C K E T _ C O N S T R U C T
368 *
369 * Create a new socket for the specified Protocol Sequence.
370 * The new socket has blocking IO semantics.
371 *
372 * (see BSD UNIX socket(2)).
373 */
374
375INTERNAL rpc_socket_error_t
376rpc__bsd_socket_construct(
377    rpc_socket_t sock,
378    rpc_protseq_id_t    pseq_id,
379    rpc_transport_info_handle_t info ATTRIBUTE_UNUSED
380    )
381{
382    rpc_socket_error_t  serr = RPC_C_SOCKET_OK;
383    rpc_bsd_socket_p_t lrpc = NULL;
384
385    /* set data.point to be 0 in case we get an error
386     and have to call rpc__bsd_socket_destruct */
387    sock->data.pointer = NULL;
388
389    lrpc = calloc(1, sizeof(*lrpc));
390
391    if (!lrpc)
392    {
393        serr = ENOMEM;
394        goto error;
395    }
396
397    sock->data.pointer = (void*) lrpc;
398
399    lrpc->fd            = -1;
400    lrpc->info.peer_uid = -1;
401    lrpc->info.peer_gid = -1;
402
403    RPC_SOCKET_DISABLE_CANCEL;
404    lrpc->fd = socket(
405        (int) RPC_PROTSEQ_INQ_NAF_ID(pseq_id),
406        (int) RPC_PROTSEQ_INQ_NET_IF_ID(pseq_id),
407        0 /*(int) RPC_PROTSEQ_INQ_NET_PROT_ID(pseq_id)*/);
408    serr = ((lrpc->fd == -1) ? errno : RPC_C_SOCKET_OK);
409
410    if (serr == RPC_C_SOCKET_OK) {
411        serr = rpc__bsd_socket_set_default_options(lrpc->fd);
412        if (serr != RPC_C_SOCKET_OK)
413            close (lrpc->fd);
414    }
415    RPC_SOCKET_RESTORE_CANCEL;
416
417    if (serr)
418    {
419        goto error;
420    }
421
422done:
423    return serr;
424
425error:
426    if (lrpc)
427    {
428        rpc__bsd_socket_destruct(sock);
429    }
430
431    goto done;
432}
433
434/*
435 * R P C _ _ S O C K E T _ O P E N _ B A S I C
436 *
437 * A special version of socket_open that is used *only* by
438 * the low level initialization code when it is trying to
439 * determine what network services are supported by the host OS.
440 */
441
442PRIVATE rpc_socket_error_t
443rpc__bsd_socket_open_basic(
444    rpc_naf_id_t        naf,
445    rpc_network_if_id_t net_if,
446    rpc_network_protocol_id_t net_prot ATTRIBUTE_UNUSED,
447    rpc_socket_basic_t        *sock
448    )
449{
450    rpc_socket_error_t  serr;
451
452    /*
453     * Always pass zero as socket protocol to compensate for
454     * overloading the protocol field for named pipes
455     */
456    RPC_SOCKET_DISABLE_CANCEL;
457    *sock = socket((int) naf, (int) net_if, 0);
458    serr = ((*sock == -1) ? errno : RPC_C_SOCKET_OK);
459
460    if (serr == RPC_C_SOCKET_OK) {
461        serr = rpc__bsd_socket_set_default_options(*sock);
462        if (serr != RPC_C_SOCKET_OK)
463            close (*sock);
464    }
465    RPC_SOCKET_RESTORE_CANCEL;
466
467    return serr;
468}
469
470PRIVATE rpc_socket_error_t
471rpc__bsd_socket_close_basic(
472    rpc_socket_basic_t        sock
473    )
474{
475    rpc_socket_error_t  serr;
476
477    RPC_LOG_SOCKET_CLOSE_NTR;
478    RPC_SOCKET_DISABLE_CANCEL;
479    serr = (close(sock) == -1) ? errno : RPC_C_SOCKET_OK;
480    RPC_SOCKET_RESTORE_CANCEL;
481    RPC_LOG_SOCKET_CLOSE_XIT;
482
483    return (serr);
484}
485
486
487/*
488 * R P C _ _ S O C K E T _ C L O S E
489 *
490 * Close (destroy) a socket.
491 *
492 * (see BSD UNIX close(2)).
493 */
494
495INTERNAL rpc_socket_error_t rpc__bsd_socket_destruct
496(
497    rpc_socket_t        sock
498)
499{
500    rpc_socket_error_t  serr = RPC_C_SOCKET_OK;
501    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
502
503    if (lrpc && lrpc->fd > 0)
504    {
505
506        RPC_LOG_SOCKET_CLOSE_NTR;
507        RPC_SOCKET_DISABLE_CANCEL;
508        serr = (close(lrpc->fd) == -1) ? errno : RPC_C_SOCKET_OK;
509        RPC_SOCKET_RESTORE_CANCEL;
510        RPC_LOG_SOCKET_CLOSE_XIT;
511    }
512
513    if (lrpc)
514    {
515	free(lrpc);
516        sock->data.pointer = NULL;
517    }
518
519    return serr;
520}
521
522/*
523 * R P C _ _ S O C K E T _ B I N D
524 *
525 * Bind a socket to a specified local address.
526 *
527 * (see BSD UNIX bind(2)).
528 */
529
530INTERNAL rpc_socket_error_t rpc__bsd_socket_bind
531(
532    rpc_socket_t        sock,
533    rpc_addr_p_t        addr
534)
535{
536    rpc_socket_error_t  serr = EINVAL;
537    unsigned32 status;
538    rpc_addr_p_t temp_addr = NULL;
539    boolean has_endpoint = false;
540    int setsock_val = 1;
541    int ncalrpc;
542    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
543
544    RPC_LOG_SOCKET_BIND_NTR;
545
546    ncalrpc = addr->rpc_protseq_id == rpc_c_protseq_id_ncalrpc;
547
548    /*
549     * Check if the address has a well-known endpoint.
550     */
551    if (addr->rpc_protseq_id == rpc_c_protseq_id_ncacn_ip_tcp || ncalrpc)
552    {
553        unsigned_char_t *endpoint;
554
555        rpc__naf_addr_inq_endpoint (addr, &endpoint, &status);
556
557        if (status == rpc_s_ok && endpoint != NULL)
558        {
559            if (endpoint[0] != '\0')    /* test for null string */
560                has_endpoint = true;
561
562            rpc_string_free (&endpoint, &status);
563        }
564        status = rpc_s_ok;
565    }
566
567    /*
568     * If there is no port restriction in this address family, then do a
569     * simple bind.
570     */
571
572    if (! RPC_PROTSEQ_TEST_PORT_RESTRICTION (addr -> rpc_protseq_id))
573    {
574        if (!has_endpoint && ncalrpc)
575        {
576            serr = 0;
577        }
578        else
579        {
580#if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
581	    setsockopt(lrpc->fd, SOL_SOCKET, SO_REUSEADDR,
582		       &setsock_val, sizeof(setsock_val));
583#endif
584            if (addr->sa.family == AF_UNIX && addr->sa.data[0] != '\0')
585            {
586                // This function is going to bind a named socket. First, try
587                // to delete the path incase a previous instance of a program
588                // left it behind.
589                //
590                // Ignore any errors from this function.
591                unlink((const char*)addr->sa.data);
592            }
593            serr =
594                (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1) ?
595                      errno : RPC_C_SOCKET_OK;
596        }
597    }                                   /* no port restriction */
598
599    else
600    {
601        /*
602         * Port restriction is in place.  If the address has a well-known
603         * endpoint, then do a simple bind.
604         */
605
606        if (has_endpoint)
607        {
608#if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
609	    setsockopt(lrpc->fd, SOL_SOCKET, SO_REUSEADDR,
610		       &setsock_val, sizeof(setsock_val));
611#endif
612            serr = (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1)?
613                errno : RPC_C_SOCKET_OK;
614        }                               /* well-known endpoint */
615        else
616	{
617
618	    unsigned_char_t *endpoint;
619	    unsigned char c;
620
621	    rpc__naf_addr_inq_endpoint (addr, &endpoint, &status);
622
623	    c = endpoint[0];               /* grab first char */
624	    rpc_string_free (&endpoint, &status);
625
626	    if (c != '\0')       /* test for null string */
627	    {
628	        serr = (bind(lrpc->fd, (struct sockaddr *)&addr->sa, addr->len) == -1)?
629		    errno : RPC_C_SOCKET_OK;
630	    }                               /* well-known endpoint */
631
632	    else
633	    {
634	        /*
635	         * Port restriction is in place and the address doesn't have a
636	         * well-known endpoint.  Try to bind until we hit a good port,
637	         * or exhaust the retry count.
638	         *
639	         * Make a copy of the address to work in; if we hardwire an
640	         * endpoint into our caller's address, later logic could infer
641	         * that it is a well-known endpoint.
642	         */
643
644	        unsigned32 i;
645	        boolean found;
646
647	        for (i = 0, found = false;
648		     (i < RPC_PORT_RESTRICTION_INQ_N_TRIES (addr->rpc_protseq_id))
649		     && !found;
650		     i++)
651	        {
652		    unsigned_char_p_t port_name;
653
654		    rpc__naf_addr_overcopy (addr, &temp_addr, &status);
655
656		    if (status != rpc_s_ok)
657		    {
658		        serr = RPC_C_SOCKET_EIO;
659		        break;
660		    }
661
662		    rpc__naf_get_next_restricted_port (temp_addr -> rpc_protseq_id,
663						   &port_name, &status);
664
665		    if (status != rpc_s_ok)
666		    {
667		        serr = RPC_C_SOCKET_EIO;
668		        break;
669		    }
670
671		    rpc__naf_addr_set_endpoint (port_name, &temp_addr, &status);
672
673		    if (status != rpc_s_ok)
674		    {
675		        serr = RPC_C_SOCKET_EIO;
676		        rpc_string_free (&port_name, &status);
677		        break;
678		    }
679
680		    if (bind(lrpc->fd, (struct sockaddr *)&temp_addr->sa, temp_addr->len) == 0)
681		    {
682		        found = true;
683		        serr = RPC_C_SOCKET_OK;
684		    }
685		    else
686		        serr = RPC_C_SOCKET_EIO;
687
688		    rpc_string_free (&port_name, &status);
689	        }                           /* for i */
690
691	        if (!found)
692	        {
693		    serr = RPC_C_SOCKET_EADDRINUSE;
694	        }
695	    }                               /* no well-known endpoint */
696        }				/* has endpoint */
697    }                                   /* port restriction is in place */
698
699    if (serr == RPC_C_SOCKET_OK && ncalrpc && has_endpoint)
700    {
701	struct sockaddr_un *skun = (struct sockaddr_un *)&addr->sa;
702
703	serr = chmod(skun->sun_path,
704		     S_IRUSR | S_IWUSR | S_IXUSR |
705		     S_IRGRP | S_IWGRP | S_IXGRP |
706		     S_IROTH | S_IWOTH | S_IXOTH) == -1 ? errno : RPC_C_SOCKET_OK;
707    }
708
709    if (temp_addr != NULL)
710        rpc__naf_addr_free (&temp_addr, &status);
711
712    RPC_LOG_SOCKET_BIND_XIT;
713    return (serr);
714}
715
716INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeereid
717(
718    rpc_socket_t        sock,
719    uid_t		*euid,
720    gid_t		*egid
721);
722
723#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
724
725INTERNAL rpc_socket_error_t rpc__bsd_socket_sendpeereid
726(
727    rpc_socket_t        sock,
728    rpc_addr_p_t        addr
729);
730
731INTERNAL rpc_socket_error_t rpc__bsd_socket_recvpeereid
732(
733    rpc_socket_t        sock,
734    uid_t		*euid,
735    gid_t		*egid
736);
737
738#endif
739
740
741/*
742 * R P C _ _ S O C K E T _ C O N N E C T
743 *
744 * Connect a socket to a specified peer's address.
745 * This is used only by Connection oriented Protocol Services.
746 *
747 * (see BSD UNIX connect(2)).
748 */
749
750INTERNAL rpc_socket_error_t rpc__bsd_socket_connect
751(
752    rpc_socket_t        sock,
753    rpc_addr_p_t        addr,
754    rpc_cn_assoc_t      *assoc ATTRIBUTE_UNUSED
755)
756{
757    rpc_socket_error_t  serr;
758    //rpc_binding_rep_t *binding_rep;
759    unsigned_char_t *netaddr, *endpoint;
760    unsigned32      dbg_status;
761    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
762
763    rpc__naf_addr_inq_netaddr (addr,
764                               &netaddr,
765                               &dbg_status);
766    rpc__naf_addr_inq_endpoint (addr,
767                               &endpoint,
768                               &dbg_status);
769
770    RPC_DBG_PRINTF (rpc_e_dbg_general, RPC_C_CN_DBG_GENERAL,
771        ("CN: connection request initiated to %s[%s]\n",
772         netaddr,
773         endpoint));
774
775connect_again:
776    RPC_LOG_SOCKET_CONNECT_NTR;
777    serr = (connect (
778                (int) lrpc->fd,
779                (struct sockaddr *) (&addr->sa),
780                (int) (addr->len))
781            == -1) ? errno : RPC_C_SOCKET_OK;
782    RPC_LOG_SOCKET_CONNECT_XIT;
783    if (serr == EINTR)
784    {
785        goto connect_again;
786    }
787    else if (serr != RPC_C_SOCKET_OK)
788    {
789        goto error;
790    }
791
792#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
793    serr = rpc__bsd_socket_sendpeereid(sock, addr);
794#endif
795
796cleanup:
797    rpc_string_free (&netaddr, &dbg_status);
798    rpc_string_free (&endpoint, &dbg_status);
799
800    return serr;
801
802error:
803    goto cleanup;
804}
805
806/*
807 * R P C _ _ S O C K E T _ A C C E P T
808 *
809 * Accept a connection on a socket, creating a new socket for the new
810 * connection.  A rpc_addr_t appropriate for the NAF corresponding to
811 * this socket must be provided.  addr.len must set to the actual size
812 * of addr.sa.  This operation fills in addr.sa and sets addr.len to
813 * the new size of the field.  This is used only by Connection oriented
814 * Protocol Services.
815 *
816 * (see BSD UNIX accept(2)).
817 */
818
819INTERNAL rpc_socket_error_t rpc__bsd_socket_accept
820(
821    rpc_socket_t        sock,
822    rpc_addr_p_t        addr,
823    rpc_socket_t        *newsock
824)
825{
826    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
827    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
828    rpc_bsd_socket_p_t newlrpc = NULL;
829    uid_t euid = -1;
830    gid_t egid = -1;
831
832    *newsock = malloc(sizeof (**newsock));
833
834    if (!*newsock)
835    {
836        return ENOMEM;
837    }
838
839    (*newsock)->vtbl = sock->vtbl;
840    (*newsock)->pseq_id = sock->pseq_id;
841
842    newlrpc = malloc(sizeof(*newlrpc));
843    if (!newlrpc)
844    {
845        return ENOMEM;
846    }
847
848    newlrpc->info.peer_uid = -1;
849    newlrpc->info.peer_gid = -1;
850
851    (*newsock)->data.pointer = newlrpc;
852
853accept_again:
854    RPC_LOG_SOCKET_ACCEPT_NTR;
855    if (addr == NULL)
856    {
857        socklen_t addrlen;
858
859        addrlen = 0;
860        newlrpc->fd = accept
861            ((int) lrpc->fd, (struct sockaddr *) NULL, &addrlen);
862    }
863    else
864    {
865        newlrpc->fd = accept
866            ((int) lrpc->fd, (struct sockaddr *) (&addr->sa), (&addr->len));
867    }
868    serr = (newlrpc->fd == -1) ? errno : RPC_C_SOCKET_OK;
869    RPC_LOG_SOCKET_ACCEPT_XIT;
870
871    if (!serr)
872    {
873        serr = rpc__bsd_socket_getpeereid((*newsock), &euid, &egid);
874    }
875    else
876    {
877        goto cleanup;
878    }
879
880    if (serr == EINTR)
881    {
882        goto accept_again;
883    }
884
885    newlrpc->info.peer_uid = euid;
886    newlrpc->info.peer_gid = egid;
887
888cleanup:
889    if (serr && newlrpc)
890    {
891        free(newlrpc);
892    }
893
894    if (serr && *newsock)
895    {
896        free(*newsock);
897    }
898
899    return serr;
900}
901
902/*
903 * R P C _ _ S O C K E T _ L I S T E N
904 *
905 * Listen for a connection on a socket.
906 * This is used only by Connection oriented Protocol Services.
907 *
908 * (see BSD UNIX listen(2)).
909 */
910
911INTERNAL rpc_socket_error_t rpc__bsd_socket_listen
912(
913    rpc_socket_t        sock,
914    int                 backlog
915)
916{
917    rpc_socket_error_t  serr;
918    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
919
920    RPC_LOG_SOCKET_LISTEN_NTR;
921    RPC_SOCKET_DISABLE_CANCEL;
922    serr = (listen(lrpc->fd, backlog) == -1) ? errno : RPC_C_SOCKET_OK;
923    RPC_SOCKET_RESTORE_CANCEL;
924    RPC_LOG_SOCKET_LISTEN_XIT;
925    return (serr);
926}
927
928/*
929 * R P C _ _ S O C K E T _ S E N D M S G
930 *
931 * Send a message over a given socket.  An error code as well as the
932 * actual number of bytes sent are returned.
933 *
934 * (see BSD UNIX sendmsg(2)).
935 */
936
937INTERNAL rpc_socket_error_t rpc__bsd_socket_sendmsg
938(
939    rpc_socket_t        sock,
940    rpc_socket_iovec_p_t iov,       /* array of bufs of data to send */
941    int                 iovcnt,     /* number of bufs */
942    rpc_addr_p_t        addr,       /* addr of receiver */
943    size_t              *cc         /* returned number of bytes actually sent */
944)
945{
946    ssize_t             ret;
947    rpc_socket_error_t  serr;
948    struct msghdr       msg;
949    rpc_bsd_socket_p_t  lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
950
951    *cc = 0;
952
953sendmsg_again:
954
955    memset(&msg, 0, sizeof(msg));
956    RPC_LOG_SOCKET_SENDMSG_NTR;
957    RPC_SOCKET_INIT_MSGHDR(&msg);
958    if ((addr) != NULL)
959    {
960        RPC_SOCKET_FIX_ADDRLEN(addr);
961        msg.msg_name = (caddr_t) &(addr)->sa;
962        msg.msg_namelen = (addr)->len;
963    }
964    else
965    {
966        msg.msg_name = (caddr_t) NULL;
967    }
968    msg.msg_iov = iov;
969    msg.msg_iovlen = iovcnt;
970
971    ret = dcethread_sendmsg (lrpc->fd, &msg, 0);
972    if (ret == (size_t) -1)
973    {
974        serr = errno;
975    }
976    else
977    {
978        serr = RPC_C_SOCKET_OK;
979        *cc = ret;
980    }
981
982    RPC_LOG_SOCKET_SENDMSG_XIT;
983    if (serr == EINTR)
984    {
985        goto sendmsg_again;
986    }
987
988    return (serr);
989}
990
991/*
992 * R P C _ _ S O C K E T _ R E C V F R O M
993 *
994 * Recieve the next buffer worth of information from a socket.  A
995 * rpc_addr_t appropriate for the NAF corresponding to this socket must
996 * be provided.  addr.len must set to the actual size of addr.sa.  This
997 * operation fills in addr.sa and sets addr.len to the new size of the
998 * field.  An error status as well as the actual number of bytes received
999 * are also returned.
1000 *
1001 * (see BSD UNIX recvfrom(2)).
1002 */
1003
1004INTERNAL rpc_socket_error_t rpc__bsd_socket_recvfrom
1005(
1006    rpc_socket_t        sock,
1007    byte_p_t            buf,        /* buf for rcvd data */
1008    int                 len,        /* len of above buf */
1009    rpc_addr_p_t        from,       /* addr of sender */
1010    size_t              *cc         /* returned number of bytes actually rcvd */
1011)
1012{
1013    ssize_t             ret;
1014    rpc_socket_error_t  serr;
1015    struct msghdr       msg;
1016    rpc_bsd_socket_p_t  lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1017
1018    *cc = 0;
1019
1020recvfrom_again:
1021    if (from != NULL)
1022    {
1023        RPC_SOCKET_FIX_ADDRLEN(from);
1024    }
1025
1026    RPC_LOG_SOCKET_RECVFROM_NTR;
1027
1028    ret = dcethread_recvfrom(lrpc->fd, buf, len, 0 /* flags */,
1029                    &from->sa, &from->len);
1030    if (ret == (size_t) -1)
1031    {
1032        serr = errno;
1033    }
1034    else
1035    {
1036        serr = RPC_C_SOCKET_OK;
1037        *cc = ret;
1038    }
1039
1040    RPC_LOG_SOCKET_RECVFROM_XIT;
1041    RPC_SOCKET_FIX_ADDRLEN(from);
1042    if (serr == EINTR)
1043    {
1044        goto recvfrom_again;
1045    }
1046
1047    return serr;
1048}
1049
1050/*
1051 * R P C _ _ S O C K E T _ R E C V M S G
1052 *
1053 * Receive a message over a given socket.  A rpc_addr_t appropriate for
1054 * the NAF corresponding to this socket must be provided.  addr.len must
1055 * set to the actual size of addr.sa.  This operation fills in addr.sa
1056 * and sets addr.len to the new size of the field.  An error code as
1057 * well as the actual number of bytes received are also returned.
1058 *
1059 * (see BSD UNIX recvmsg(2)).
1060 */
1061
1062INTERNAL rpc_socket_error_t rpc__bsd_socket_recvmsg
1063(
1064    rpc_socket_t        sock,
1065    rpc_socket_iovec_p_t iov,       /* array of bufs for rcvd data */
1066    int                 iovcnt,    /* number of bufs */
1067    rpc_addr_p_t        addr,       /* addr of sender */
1068    size_t              *cc         /* returned number of bytes actually rcvd */
1069)
1070{
1071    ssize_t             ret;
1072    rpc_socket_error_t  serr;
1073    struct msghdr       msg;
1074    rpc_bsd_socket_p_t  lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1075    int block = 0;
1076
1077    *cc = 0;
1078
1079recvmsg_again:
1080
1081    memset(&msg, 0, sizeof(msg));
1082    RPC_LOG_SOCKET_RECVMSG_NTR;
1083    RPC_SOCKET_INIT_MSGHDR(&msg);
1084    if (addr != NULL)
1085    {
1086        RPC_SOCKET_FIX_ADDRLEN(addr);
1087        msg.msg_name = (caddr_t) &addr->sa;
1088        msg.msg_namelen = addr->len;
1089    }
1090    else
1091    {
1092        msg.msg_name = (caddr_t) NULL;
1093    }
1094    msg.msg_iov =  iov;
1095    msg.msg_iovlen = iovcnt;
1096
1097    /*
1098     * WORKAROUND :
1099     * - Inconsistency between kernel socket state and socket file descriptor state -
1100     * fcntl(F_GETFL) here tells us that socket is blocking (O_NONBLOCK not set in flags),
1101     * however kernel dtrace probe for soreceive says socket is SS_NBIO.
1102     * See 18110085 / 17781539 for details.
1103     * Setting FIONBIO to 0 from userland will resolve this incosistency and make both
1104     * socket state and socket file descriptor state in the kernel land, and gurantees a
1105     * blocking socket before recvmsg() is called.
1106     */
1107    ioctl(lrpc->fd, FIONBIO, &block);
1108
1109    ret = dcethread_recvmsg (lrpc->fd, &msg, 0);
1110    if (ret == (ssize_t)-1)
1111    {
1112        serr = errno;
1113    }
1114    else
1115    {
1116        serr = RPC_C_SOCKET_OK;
1117        *cc = ret;
1118    }
1119
1120    RPC_LOG_SOCKET_RECVMSG_XIT;
1121    if (serr == EINTR)
1122    {
1123        goto recvmsg_again;
1124    }
1125
1126    if (addr != NULL)
1127    {
1128        addr->len = msg.msg_namelen;
1129    }
1130
1131    return serr;
1132}
1133
1134/*
1135 * R P C _ _ S O C K E T _ I N Q _ A D D R
1136 *
1137 * Return the local address associated with a socket.  A rpc_addr_t
1138 * appropriate for the NAF corresponding to this socket must be provided.
1139 * addr.len must set to the actual size of addr.sa.  This operation fills
1140 * in addr.sa and sets addr.len to the new size of the field.
1141 *
1142 * !!! NOTE: You should use rpc__naf_desc_inq_addr() !!!
1143 *
1144 * This routine is indended for use only by the internal routine:
1145 * rpc__naf_desc_inq_addr().  rpc__bsd_socket_inq_endpoint() only has the
1146 * functionality of BSD UNIX getsockname() which doesn't (at least not
1147 * on all systems) return the local network portion of a socket's address.
1148 * rpc__naf_desc_inq_addr() returns the complete address for a socket.
1149 *
1150 * (see BSD UNIX getsockname(2)).
1151 */
1152
1153INTERNAL rpc_socket_error_t rpc__bsd_socket_inq_endpoint
1154(
1155    rpc_socket_t        sock,
1156    rpc_addr_p_t        addr
1157)
1158{
1159    rpc_socket_error_t  serr;
1160    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1161
1162    RPC_LOG_SOCKET_INQ_EP_NTR;
1163    RPC_SOCKET_FIX_ADDRLEN(addr);
1164    RPC_SOCKET_DISABLE_CANCEL;
1165    serr = (getsockname(lrpc->fd, (void*)&addr->sa, &addr->len) == -1) ? errno : RPC_C_SOCKET_OK;
1166    RPC_SOCKET_RESTORE_CANCEL;
1167    RPC_SOCKET_FIX_ADDRLEN(addr);
1168    RPC_LOG_SOCKET_INQ_EP_XIT;
1169    return (serr);
1170}
1171
1172/*
1173 * R P C _ _ S O C K E T _ S E T _ B R O A D C A S T
1174 *
1175 * Enable broadcasting for the socket (as best it can).
1176 * Used only by Datagram based Protocol Services.
1177 */
1178
1179INTERNAL rpc_socket_error_t rpc__bsd_socket_set_broadcast
1180(
1181    rpc_socket_t        sock
1182)
1183{
1184#ifdef SO_BROADCAST
1185    int                 setsock_val = 1;
1186    rpc_socket_error_t  serr;
1187    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1188
1189    RPC_SOCKET_DISABLE_CANCEL;
1190    serr = (setsockopt(lrpc->fd, SOL_SOCKET, SO_BROADCAST,
1191            &setsock_val, sizeof(setsock_val)) == -1) ? errno : RPC_C_SOCKET_OK;
1192    RPC_SOCKET_RESTORE_CANCEL;
1193    if (serr)
1194    {
1195        RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_broadcast) error=%d\n", serr));
1196    }
1197
1198    return(serr);
1199#else
1200    return(RPC_C_SOCKET_OK);
1201#endif
1202}
1203
1204/*
1205 * R P C _ _ S O C K E T _ S E T _ B U F S
1206 *
1207 * Set the socket's send and receive buffer sizes and return the new
1208 * values.  Note that the sizes are min'd with
1209 * "rpc_c_socket_max_{snd,rcv}buf" because systems tend to fail the
1210 * operation rather than give the max buffering if the max is exceeded.
1211 *
1212 * If for some reason your system is screwed up and defines SOL_SOCKET
1213 * and SO_SNDBUF, but doesn't actually support the SO_SNDBUF and SO_RCVBUF
1214 * operations AND using them would result in nasty behaviour (i.e. they
1215 * don't just return some error code), define NO_SO_SNDBUF.
1216 *
1217 * If the buffer sizes provided are 0, then we use the operating
1218 * system default (i.e. we don't set anything at all).
1219 */
1220
1221INTERNAL rpc_socket_error_t rpc__bsd_socket_set_bufs
1222(
1223    rpc_socket_t        sock,
1224    unsigned32          txsize,
1225    unsigned32          rxsize,
1226    unsigned32          *ntxsize,
1227    unsigned32          *nrxsize
1228)
1229{
1230    socklen_t sizelen;
1231    int e;
1232    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1233
1234    RPC_SOCKET_DISABLE_CANCEL;
1235
1236#if (defined (SOL_SOCKET) && defined(SO_SNDBUF)) && !defined(NO_SO_SNDBUF)
1237
1238    /*
1239     * Set the new sizes.
1240     */
1241
1242    txsize = MIN(txsize, RPC_C_SOCKET_MAX_SNDBUF);
1243    if (txsize != 0)
1244    {
1245        e = setsockopt(lrpc->fd, SOL_SOCKET, SO_SNDBUF, &txsize, sizeof(txsize));
1246        if (e == -1)
1247        {
1248            RPC_DBG_GPRINTF
1249                (("(rpc__bsd_socket_set_bufs) WARNING: set sndbuf (%d) failed - error = %d\n",
1250                txsize, errno));
1251        }
1252    }
1253
1254    rxsize = MIN(rxsize, RPC_C_SOCKET_MAX_RCVBUF);
1255    if (rxsize != 0)
1256    {
1257        e = setsockopt(lrpc->fd, SOL_SOCKET, SO_RCVBUF, &rxsize, sizeof(rxsize));
1258        if (e == -1)
1259        {
1260            RPC_DBG_GPRINTF
1261                (("(rpc__bsd_socket_set_bufs) WARNING: set rcvbuf (%d) failed - error = %d\n",
1262                rxsize, errno));
1263        }
1264    }
1265
1266    /*
1267     * Get the new sizes.  If this fails, just return some guessed sizes.
1268     */
1269    *ntxsize = 0;
1270    sizelen = sizeof *ntxsize;
1271    e = getsockopt(lrpc->fd, SOL_SOCKET, SO_SNDBUF, ntxsize, &sizelen);
1272    if (e == -1)
1273    {
1274        RPC_DBG_GPRINTF
1275            (("(rpc__bsd_socket_set_bufs) WARNING: get sndbuf failed - error = %d\n", errno));
1276        *ntxsize = RPC_C_SOCKET_GUESSED_SNDBUF;
1277    }
1278
1279    *nrxsize = 0;
1280    sizelen = sizeof *nrxsize;
1281    e = getsockopt(lrpc->fd, SOL_SOCKET, SO_RCVBUF, nrxsize, &sizelen);
1282    if (e == -1)
1283    {
1284        RPC_DBG_GPRINTF
1285            (("(rpc__bsd_socket_set_bufs) WARNING: get rcvbuf failed - error = %d\n", errno));
1286        *nrxsize = RPC_C_SOCKET_GUESSED_RCVBUF;
1287    }
1288
1289#  ifdef apollo
1290    /*
1291     * On Apollo, modifying the socket buffering doesn't actually do
1292     * anything on IP sockets, but the calls succeed anyway.  We can
1293     * detect this by the fact that the new buffer length returned is
1294     * 0. Return what we think the actually length is.
1295     */
1296    if (rxsize != 0 && *nrxsize == 0)
1297    {
1298        *nrxsize = (8 * 1024);
1299    }
1300    if (txsize != 0 && *ntxsize == 0)
1301    {
1302        *ntxsize = (8 * 1024);
1303    }
1304#  endif
1305
1306#else
1307
1308    *ntxsize = RPC_C_SOCKET_GUESSED_SNDBUF;
1309    *nrxsize = RPC_C_SOCKET_GUESSED_RCVBUF;
1310
1311#endif
1312
1313    RPC_SOCKET_RESTORE_CANCEL;
1314
1315    return (RPC_C_SOCKET_OK);
1316}
1317
1318/*
1319 * R P C _ _ S O C K E T _ S E T _ N B I O
1320 *
1321 * Set a socket to non-blocking mode.
1322 *
1323 * Return RPC_C_SOCKET_OK on success, otherwise an error value.
1324 */
1325
1326INTERNAL rpc_socket_error_t rpc__bsd_socket_set_nbio
1327(
1328    rpc_socket_t        sock
1329)
1330{
1331    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1332    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1333
1334    RPC_SOCKET_DISABLE_CANCEL;
1335    serr = ((fcntl(lrpc->fd, F_SETFL, O_NDELAY) == -1) ? errno : RPC_C_SOCKET_OK);
1336    RPC_SOCKET_RESTORE_CANCEL;
1337    if (serr)
1338    {
1339        RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_nbio) error=%d\n", serr));
1340    }
1341
1342    return (serr);
1343}
1344
1345/*
1346 * R P C _ _ S O C K E T _ S E T _ C L O S E _ O N _ E X E C
1347 *
1348 *
1349 * Set a socket to a mode whereby it is not inherited by a spawned process
1350 * executing some new image. This is possibly a no-op on some systems.
1351 *
1352 * Return RPC_C_SOCKET_OK on success, otherwise an error value.
1353 */
1354
1355INTERNAL rpc_socket_error_t rpc__bsd_socket_set_close_on_exec
1356(
1357    rpc_socket_t        sock
1358)
1359{
1360    rpc_socket_error_t  serr = RPC_C_SOCKET_OK;
1361    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1362
1363    RPC_SOCKET_DISABLE_CANCEL;
1364    serr = ((fcntl(lrpc->fd, F_SETFD, 1) == -1) ? errno : RPC_C_SOCKET_OK);
1365    RPC_SOCKET_RESTORE_CANCEL;
1366    if (serr)
1367    {
1368        RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_close_on_exec) error=%d\n", serr));
1369    }
1370    return (serr);
1371}
1372
1373/*
1374 * R P C _ _ S O C K E T _ G E T P E E R N A M E
1375 *
1376 * Get name of connected peer.
1377 * This is used only by Connection oriented Protocol Services.
1378 *
1379 * (see BSD UNIX getpeername(2)).
1380 */
1381
1382INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeername
1383(
1384    rpc_socket_t sock,
1385    rpc_addr_p_t addr
1386)
1387{
1388    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1389    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1390
1391    RPC_SOCKET_FIX_ADDRLEN(addr);
1392    RPC_SOCKET_DISABLE_CANCEL;
1393    serr = (getpeername(lrpc->fd, (void *)&addr->sa, &addr->len) == -1) ? errno : RPC_C_SOCKET_OK;
1394    RPC_SOCKET_RESTORE_CANCEL;
1395    RPC_SOCKET_FIX_ADDRLEN(addr);
1396
1397    return (serr);
1398}
1399
1400/*
1401 * R P C _ _ S O C K E T _ G E T _ I F _ I D
1402 *
1403 * Get socket network interface id (socket type).
1404 *
1405 * (see BSD UNIX getsockopt(2)).
1406 */
1407
1408INTERNAL rpc_socket_error_t rpc__bsd_socket_get_if_id
1409(
1410    rpc_socket_t        sock,
1411    rpc_network_if_id_t *network_if_id
1412)
1413{
1414    socklen_t optlen = 0;
1415    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1416    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1417
1418    optlen = sizeof(rpc_network_if_id_t);
1419
1420    RPC_SOCKET_DISABLE_CANCEL;
1421    serr = (getsockopt (lrpc->fd,
1422                        SOL_SOCKET,
1423                        SO_TYPE,
1424                        network_if_id,
1425                        &optlen) == -1  ? errno : RPC_C_SOCKET_OK);
1426    RPC_SOCKET_RESTORE_CANCEL;
1427    return serr;
1428}
1429
1430/*
1431 * R P C _ _ S O C K E T _ S E T _ K E E P A L I V E
1432 *
1433 * Enable periodic transmissions on a connected socket, when no
1434 * other data is being exchanged. If the other end does not respond to
1435 * these messages, the connection is considered broken and the
1436 * so_error variable is set to ETIMEDOUT.
1437 * Used only by Connection based Protocol Services.
1438 *
1439 * (see BSD UNIX setsockopt(2)).
1440 */
1441
1442INTERNAL rpc_socket_error_t rpc__bsd_socket_set_keepalive
1443(
1444    rpc_socket_t        sock
1445)
1446{
1447#ifdef SO_KEEPALIVE
1448    int                 setsock_val = 1;
1449    rpc_socket_error_t  serr = RPC_C_SOCKET_OK;
1450    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1451
1452    RPC_SOCKET_DISABLE_CANCEL;
1453    serr = ((setsockopt(lrpc->fd, SOL_SOCKET, SO_KEEPALIVE,
1454       &setsock_val, sizeof(setsock_val)) == -1) ? errno : RPC_C_SOCKET_OK);
1455    RPC_SOCKET_RESTORE_CANCEL;
1456    if (serr)
1457    {
1458        RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_keepalive) error=%d\n", serr));
1459    }
1460
1461    return(serr);
1462#else
1463    return(RPC_C_SOCKET_OK);
1464#endif
1465}
1466
1467
1468/*
1469 * R P C _ _ S O C K E T _ N O W R I T E B L O C K _ W A I T
1470 *
1471 * Wait until the a write on the socket should succede without
1472 * blocking.  If tmo is NULL, the wait is unbounded, otherwise
1473 * tmo specifies the max time to wait. RPC_C_SOCKET_ETIMEDOUT
1474 * if a timeout occurs.  This operation in not cancellable.
1475 */
1476
1477INTERNAL rpc_socket_error_t rpc__bsd_socket_nowriteblock_wait
1478(
1479    rpc_socket_t sock,
1480    struct timeval *tmo
1481)
1482{
1483    fd_set  write_fds;
1484    int     nfds, num_found;
1485    rpc_socket_error_t  serr = RPC_C_SOCKET_OK;
1486    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1487
1488    FD_ZERO (&write_fds);
1489    FD_SET (lrpc->fd, &write_fds);
1490    nfds = lrpc->fd + 1;
1491
1492    RPC_SOCKET_DISABLE_CANCEL;
1493    num_found = dcethread_select(nfds, NULL, (void *)&write_fds, NULL, tmo);
1494    serr = ((num_found < 0) ? errno : RPC_C_SOCKET_OK);
1495    RPC_SOCKET_RESTORE_CANCEL;
1496
1497    if (serr)
1498    {
1499        RPC_DBG_GPRINTF(("(rpc__bsd_socket_nowriteblock_wait) error=%d\n", serr));
1500        return serr;
1501    }
1502
1503    if (num_found == 0)
1504    {
1505        RPC_DBG_GPRINTF(("(rpc__bsd_socket_nowriteblock_wait) timeout\n"));
1506        return RPC_C_SOCKET_ETIMEDOUT;
1507    }
1508
1509    return RPC_C_SOCKET_OK;
1510}
1511
1512
1513/*
1514 * R P C _ _ S O C K E T _ S E T _ R C V T I M E O
1515 *
1516 * Set receive timeout on a socket
1517 * Used only by Connection based Protocol Services.
1518 *
1519 * (see BSD UNIX setsockopt(2)).
1520 */
1521
1522INTERNAL rpc_socket_error_t rpc__bsd_socket_set_rcvtimeo
1523(
1524    rpc_socket_t        sock,
1525    struct timeval      *tmo
1526)
1527{
1528#ifdef SO_RCVTIMEO
1529    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1530    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1531
1532    RPC_SOCKET_DISABLE_CANCEL;
1533    serr = ((setsockopt(lrpc->fd, SOL_SOCKET, SO_RCVTIMEO,
1534       tmo, sizeof(*tmo)) == -1) ? errno : RPC_C_SOCKET_OK);
1535    RPC_SOCKET_RESTORE_CANCEL;
1536    if (serr)
1537    {
1538        RPC_DBG_GPRINTF(("(rpc__bsd_socket_set_rcvtimeo) error=%d\n", serr));
1539    }
1540
1541    return(serr);
1542#else
1543    return(RPC_C_SOCKET_OK);
1544#endif
1545}
1546
1547/*
1548 * R P C _ _ S O C K E T _ G E T _ P E E R E I D
1549 *
1550 * Get UNIX domain socket peer credentials
1551 */
1552
1553INTERNAL rpc_socket_error_t rpc__bsd_socket_getpeereid
1554(
1555    rpc_socket_t        sock,
1556    uid_t		*euid,
1557    gid_t		*egid
1558)
1559{
1560    rpc_socket_error_t  serr = RPC_C_SOCKET_ENOTSUP;
1561    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1562
1563#if HAVE_GETPEEREID
1564
1565    RPC_SOCKET_DISABLE_CANCEL;
1566    serr = ((getpeereid(lrpc->fd, euid, egid) == -1) ? errno
1567                                            : RPC_C_SOCKET_OK);
1568    RPC_SOCKET_RESTORE_CANCEL;
1569
1570    if (serr != RPC_C_SOCKET_OK)
1571    {
1572        RPC_DBG_GPRINTF(("(rpc__bsd_socket_getpeereid) error=%d\n", serr));
1573    }
1574
1575#elif defined(SO_PEERCRED)
1576    struct ucred peercred = {0};
1577    socklen_t peercredlen = sizeof(peercred);
1578
1579    RPC_SOCKET_DISABLE_CANCEL;
1580    serr = ((getsockopt(lrpc->fd, SOL_SOCKET, SO_PEERCRED,
1581	&peercred, &peercredlen) == -1) ? errno : RPC_C_SOCKET_OK);
1582    RPC_SOCKET_RESTORE_CANCEL;
1583    if (serr == RPC_C_SOCKET_OK)
1584    {
1585	*euid = peercred.uid;
1586	*egid = peercred.gid;
1587    }
1588    else
1589    {
1590        RPC_DBG_GPRINTF(("(rpc__bsd_socket_getpeereid) error=%d\n", serr));
1591    }
1592#else
1593    serr = rpc__bsd_socket_recvpeereid(sock, euid, egid);
1594#endif
1595
1596    return serr;
1597}
1598
1599#if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID)
1600
1601INTERNAL rpc_socket_error_t rpc__bsd_socket_sendpeereid
1602(
1603    rpc_socket_t        sock,
1604    rpc_addr_p_t        addr
1605)
1606{
1607    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1608    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1609    struct sockaddr_un *endpoint_addr = NULL;
1610    struct stat endpoint_stat = {0};
1611    uid_t ep_uid = -1;
1612    int pipefd[2] = {-1, -1};
1613    char empty_buf[] = {'\0'};
1614    rpc_socket_iovec_t iovec = {0};
1615    union
1616    {
1617        /* Using union ensures correct alignment on some platforms */
1618        struct cmsghdr cm;
1619        char buf[CMSG_SPACE(sizeof(pipefd[0]))];
1620    } cm_un;
1621    struct msghdr msg = {0};
1622    struct cmsghdr *cmsg = NULL;
1623    int bytes_sent = 0;
1624
1625    endpoint_addr = (struct sockaddr_un *)(&addr->sa);
1626
1627    if (stat(endpoint_addr->sun_path, &endpoint_stat))
1628    {
1629        serr = errno;
1630	goto error;
1631    }
1632
1633    ep_uid = endpoint_stat.st_uid;
1634    if (ep_uid == 0 || ep_uid == getuid())
1635    {
1636        if (pipe(pipefd) != 0)
1637        {
1638                serr = errno;
1639                goto error;
1640        }
1641    }
1642
1643    iovec.iov_base     = &empty_buf;
1644    iovec.iov_len      = sizeof(empty_buf);
1645
1646    msg.msg_iov        = &iovec;
1647    msg.msg_iovlen     = 1;
1648    msg.msg_control    = cm_un.buf;
1649    msg.msg_controllen = sizeof(cm_un.buf);
1650    msg.msg_flags      = 0;
1651
1652    memset(&cm_un, 0, sizeof(cm_un));
1653
1654    cmsg = CMSG_FIRSTHDR(&msg);
1655    cmsg->cmsg_level = SOL_SOCKET;
1656    cmsg->cmsg_type  = SCM_RIGHTS;
1657    cmsg->cmsg_len   = CMSG_LEN(sizeof(pipefd[0]));
1658
1659    memcpy(CMSG_DATA(cmsg), &pipefd[0], sizeof(pipefd[0]));
1660
1661    RPC_SOCKET_DISABLE_CANCEL;
1662    bytes_sent = sendmsg(lrpc->fd, &msg, 0);
1663    RPC_SOCKET_RESTORE_CANCEL;
1664    if (bytes_sent == -1)
1665    {
1666        serr = errno;
1667        goto error;
1668    }
1669
1670cleanup:
1671
1672    if (pipefd[0] != -1)
1673    {
1674        close(pipefd[0]);
1675    }
1676
1677    if (pipefd[1] != -1)
1678    {
1679        close(pipefd[1]);
1680    }
1681
1682    return serr;
1683
1684error:
1685
1686    goto cleanup;
1687}
1688
1689INTERNAL rpc_socket_error_t rpc__bsd_socket_recvpeereid
1690(
1691    rpc_socket_t        sock,
1692    uid_t		*euid,
1693    gid_t		*egid
1694)
1695{
1696    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
1697    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1698    int fd = -1;
1699    int bytes_rcvd = 0;
1700    struct stat pipe_stat = {0};
1701    char empty_buf[] = {'\0'};
1702    rpc_socket_iovec_t iovec = {0};
1703    union
1704    {
1705        /* Using union ensures correct alignment on some platforms */
1706        struct cmsghdr cm;
1707        char buf[CMSG_SPACE(sizeof(fd))];
1708    } cm_un;
1709    struct cmsghdr *cmsg = NULL;
1710    struct msghdr msg = {0};
1711
1712    iovec.iov_base = &empty_buf;
1713    iovec.iov_len  = sizeof(empty_buf);
1714
1715    memset(&cm_un, 0, sizeof(cm_un));
1716
1717    msg.msg_iov        = &iovec;
1718    msg.msg_iovlen     = 1;
1719    msg.msg_control    = cm_un.buf;
1720    msg.msg_controllen = sizeof(cm_un.buf);
1721    msg.msg_flags      = 0;
1722
1723    RPC_SOCKET_DISABLE_CANCEL;
1724    bytes_rcvd = recvmsg(lrpc->fd, &msg, 0);
1725    RPC_SOCKET_RESTORE_CANCEL;
1726    if (bytes_rcvd == -1)
1727    {
1728        serr = errno;
1729        goto error;
1730    }
1731
1732    if (msg.msg_controllen == 0 ||
1733        msg.msg_controllen > sizeof(cm_un))
1734    {
1735        serr = RPC_C_SOCKET_EACCESS;
1736        goto error;
1737    }
1738
1739    cmsg = CMSG_FIRSTHDR(&msg);
1740    if (!cmsg ||
1741	!(cmsg->cmsg_type == SCM_RIGHTS) ||
1742        cmsg->cmsg_len - CMSG_ALIGN(sizeof(*cmsg)) != sizeof(fd))
1743    {
1744        serr = RPC_C_SOCKET_EACCESS;
1745        goto error;
1746    }
1747
1748    memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
1749
1750    if (fstat(fd, &pipe_stat))
1751    {
1752        serr = errno;
1753        goto error;
1754    }
1755
1756    if (!S_ISFIFO(pipe_stat.st_mode) ||
1757        (pipe_stat.st_mode & (S_IRWXO | S_IRWXG)) != 0)
1758    {
1759        serr = RPC_C_SOCKET_EACCESS;
1760        goto error;
1761    }
1762
1763    *euid = pipe_stat.st_uid;
1764    *egid = pipe_stat.st_gid;
1765
1766cleanup:
1767
1768    if (fd > 0)
1769    {
1770        close(fd);
1771    }
1772
1773    return serr;
1774
1775error:
1776
1777    *euid = -1;
1778    *egid = -1;
1779
1780    goto cleanup;
1781}
1782
1783#endif
1784
1785INTERNAL
1786int rpc__bsd_socket_get_select_desc(
1787    rpc_socket_t sock
1788    )
1789{
1790    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1791
1792    return lrpc->fd;
1793}
1794
1795INTERNAL
1796rpc_socket_error_t
1797rpc__bsd_socket_enum_ifaces(
1798    rpc_socket_t sock,
1799    rpc_socket_enum_iface_fn_p_t efun,
1800    rpc_addr_vector_p_t *rpc_addr_vec,
1801    rpc_addr_vector_p_t *netmask_addr_vec,
1802    rpc_addr_vector_p_t *broadcast_addr_vec
1803)
1804{
1805    rpc_ip_addr_p_t         ip_addr = NULL;
1806    rpc_ip_addr_p_t         netmask_addr = NULL;
1807    rpc_ip_addr_p_t         broadcast_addr = NULL;
1808    int                     n_ifs;
1809    union
1810    {
1811        unsigned char           buf[1024];
1812        struct ifreq req;
1813    } reqbuf;
1814    struct ifconf           ifc;
1815    struct ifreq            *ifr, *last_ifr;
1816    struct ifreq            ifreq;
1817    short                   if_flags;
1818    struct sockaddr         if_addr;
1819    unsigned int                     i;
1820#ifdef _SOCKADDR_LEN
1821    int                     prev_size;
1822#else
1823    const int prev_size = sizeof(struct ifreq) ;
1824#endif
1825    rpc_socket_error_t err = 0;
1826    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
1827
1828    /*
1829     * Get the list of network interfaces.
1830     */
1831    ifc.ifc_len = sizeof (reqbuf.buf);
1832    ifc.ifc_buf = (caddr_t) reqbuf.buf;
1833
1834ifconf_again:
1835    if (ioctl (lrpc->fd, SIOCGIFCONF, (caddr_t) &ifc) < 0)
1836    {
1837        if (errno == EINTR)
1838        {
1839            goto ifconf_again;
1840        }
1841        err = errno;   /* !!! */
1842        goto done;
1843    }
1844
1845    /*
1846     * Figure out how many interfaces there must be and allocate an
1847     * RPC address vector with the appropriate number of elements.
1848     * (We may ask for a few too many in case some of the interfaces
1849     * are uninteresting.)
1850     */
1851    n_ifs = ifc.ifc_len / sizeof (struct ifreq);
1852    RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
1853        ("%lu bytes of ifreqs, ifreq is %lu bytes\n",
1854         (unsigned long)ifc.ifc_len,
1855         (unsigned long)sizeof(struct ifreq)));
1856
1857#ifdef MAX_DEBUG
1858    if (RPC_DBG2(rpc_e_dbg_general, 15))
1859    {
1860        int i;
1861	char msgbuf[128];
1862
1863        for (i=0; i<ifc.ifc_len; i++) {
1864            if ((i % 32) == 0) {
1865		if (i != 0)
1866		    RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf));
1867                sprintf(msgbuf, "%4x: ", i);
1868	    }
1869            sprintf(msgbuf, "%s%02x ", msgbuf, reqbuf.buf[i]);
1870        }
1871	if (i != 0)
1872	    RPC_DBG_PRINTF(rpc_e_dbg_general, 15, ("%s\n",msgbuf));
1873    }
1874#endif
1875
1876    if (rpc_addr_vec != NULL)
1877    {
1878        RPC_MEM_ALLOC (
1879            *rpc_addr_vec,
1880            rpc_addr_vector_p_t,
1881            (sizeof **rpc_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))),
1882            RPC_C_MEM_RPC_ADDR_VEC,
1883            RPC_C_MEM_WAITOK);
1884
1885        if (*rpc_addr_vec == NULL)
1886        {
1887            err = ENOMEM;
1888            goto done;
1889        }
1890    }
1891
1892    if (netmask_addr_vec != NULL)
1893    {
1894        RPC_MEM_ALLOC (
1895            *netmask_addr_vec,
1896            rpc_addr_vector_p_t,
1897         (sizeof **netmask_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))),
1898            RPC_C_MEM_RPC_ADDR_VEC,
1899            RPC_C_MEM_WAITOK);
1900
1901        if (*netmask_addr_vec == NULL)
1902        {
1903            err = ENOMEM;
1904            RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
1905            goto done;
1906        }
1907
1908        (*netmask_addr_vec)->len = 0;
1909    }
1910
1911    if (broadcast_addr_vec != NULL)
1912    {
1913        RPC_MEM_ALLOC (
1914            *broadcast_addr_vec,
1915            rpc_addr_vector_p_t,
1916         (sizeof **broadcast_addr_vec) + ((n_ifs - 1) * (sizeof (rpc_addr_p_t))),
1917            RPC_C_MEM_RPC_ADDR_VEC,
1918            RPC_C_MEM_WAITOK);
1919
1920        if (*broadcast_addr_vec == NULL)
1921        {
1922            err = ENOMEM;
1923            RPC_MEM_FREE (*broadcast_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
1924            goto done;
1925        }
1926
1927        (*broadcast_addr_vec)->len = 0;
1928    }
1929
1930    /*
1931     * Go through the interfaces and get the info associated with them.
1932     */
1933    assert(rpc_addr_vec != NULL);
1934    (*rpc_addr_vec)->len = 0;
1935    last_ifr = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1936
1937    for (i=0, ifr = ifc.ifc_req; ifr < last_ifr ;
1938         i++, ifr = (struct ifreq *)(( (char *) ifr ) + prev_size))
1939    {
1940#ifdef _SOCKADDR_LEN
1941        prev_size = sizeof (struct ifreq) - sizeof(struct sockaddr) + ifr->ifr_addr.sa_len ;
1942#endif
1943        RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("interface %d: %s\n",
1944            i, ifr->ifr_name));
1945        /*
1946         * Get the interface's flags.  If the flags say that the interface
1947         * is not up or is the loopback interface, skip it.  Do the
1948         * SIOCGIFFLAGS on a copy of the ifr so we don't lose the original
1949         * contents of the ifr.  (ifr's are unions that hold only one
1950         * of the interesting interface attributes [address, flags, etc.]
1951         * at a time.)
1952         */
1953        memcpy(&ifreq, ifr, sizeof(ifreq));
1954ifflags_again:
1955        if (ioctl(lrpc->fd, SIOCGIFFLAGS, &ifreq) < 0)
1956        {
1957            RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
1958                ("SIOCGIFFLAGS returned errno %d\n", errno));
1959            if (errno == EINTR)
1960            {
1961                goto ifflags_again;
1962            }
1963            continue;
1964        }
1965        if_flags = ifreq.ifr_flags;     /* Copy out the flags */
1966        RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("flags are %x\n", if_flags));
1967
1968        /*
1969         * Ignore interfaces which are not 'up'.
1970         */
1971        if ((if_flags & IFF_UP) == 0)
1972
1973	  continue;
1974
1975#ifndef USE_LOOPBACK
1976	/*
1977	 * Ignore the loopback interface
1978	 */
1979
1980        if (if_flags & IFF_LOOPBACK) continue;
1981#endif
1982	/*
1983	 * Ignore Point-to-Point interfaces (i.e. SLIP/PPP )
1984         * *** NOTE:  We need an Environment Variable Evaluation at
1985	 * some point so we can selectively allow RPC servers to
1986	 * some up with/without SLIP/PPP bindings. For Dynamic PPP/SLIP
1987	 * interfaces, this creates problems for now.
1988	 */
1989
1990        if (if_flags & IFF_POINTOPOINT) continue;
1991
1992        /*
1993         * Get the addressing stuff for this interface.
1994         */
1995
1996#ifdef NO_SIOCGIFADDR
1997
1998        /*
1999         * Note that some systems do not return the address for the
2000         * interface given.  However the ifr array elts contained in
2001         * the ifc block returned from the SIOCGIFCONF ioctl above already
2002         * contains the correct addresses. So these systems should define
2003         * NO_SIOCGIFADDR in their platform specific include file.
2004         */
2005        if_addr = ifr->ifr_addr;
2006
2007#else
2008
2009        /*
2010         * Do the SIOCGIFADDR on a copy of the ifr.  See above.
2011         */
2012        memcpy(&ifreq, ifr, sizeof(ifreq));
2013    ifaddr_again:
2014        if (ioctl(lrpc->fd, SIOCGIFADDR, &ifreq) < 0)
2015        {
2016            /*
2017             * UP but no ip address, skip it
2018             */
2019            if (errno == EADDRNOTAVAIL) continue;
2020
2021            RPC_DBG_PRINTF(rpc_e_dbg_general, 10,
2022                           ("SIOCGIFADDR returned errno %d\n", errno));
2023            if (errno == EINTR)
2024            {
2025                goto ifaddr_again;
2026            }
2027
2028            err = errno;
2029            goto FREE_IT;
2030        }
2031
2032        memcpy (&if_addr, &ifr->ifr_addr, sizeof(struct sockaddr));
2033
2034#endif  /* NO_SIOCGIFADDR */
2035
2036        /*
2037         * If this isn't an Internet-family address, ignore it.
2038         */
2039        if (if_addr.sa_family != AF_INET)
2040        {
2041            RPC_DBG_PRINTF(rpc_e_dbg_general, 10, ("AF %d not INET\n",
2042                                                   if_addr.sa_family));
2043            continue;
2044        }
2045
2046        if (rpc_addr_vec != NULL)
2047        {
2048            /*
2049             * Allocate and fill in an IP RPC address for this interface.
2050             */
2051            RPC_MEM_ALLOC (
2052                ip_addr,
2053                rpc_ip_addr_p_t,
2054                sizeof (rpc_ip_addr_t),
2055                RPC_C_MEM_RPC_ADDR,
2056                RPC_C_MEM_WAITOK);
2057
2058            if (ip_addr == NULL)
2059            {
2060                err = ENOMEM;
2061                goto FREE_IT;
2062            }
2063
2064            ip_addr->rpc_protseq_id = sock->pseq_id;
2065            ip_addr->len            = sizeof (struct sockaddr_in);
2066
2067            memcpy (&ip_addr->sa, &if_addr, sizeof(struct sockaddr_in));
2068        }
2069        else
2070        {
2071            ip_addr = NULL;
2072        }
2073
2074        if (netmask_addr_vec != NULL && (if_flags & IFF_LOOPBACK) == 0)
2075        {
2076            memcpy(&ifreq, ifr, sizeof(ifreq));
2077
2078            while (ioctl(lrpc->fd, SIOCGIFNETMASK, &ifreq) == -1)
2079            {
2080                if (errno != EINTR)
2081                {
2082                    err = errno;
2083                    goto FREE_IT;
2084                }
2085            }
2086
2087            RPC_MEM_ALLOC (
2088                netmask_addr,
2089                rpc_ip_addr_p_t,
2090                sizeof (rpc_ip_addr_t),
2091                RPC_C_MEM_RPC_ADDR,
2092                RPC_C_MEM_WAITOK);
2093
2094            if (netmask_addr == NULL)
2095            {
2096                err = ENOMEM;
2097                goto FREE_IT;
2098            }
2099
2100            netmask_addr->rpc_protseq_id = sock->pseq_id;
2101            netmask_addr->len            = sizeof (struct sockaddr_in);
2102            memcpy(&netmask_addr->sa, &ifreq.ifr_addr, sizeof(struct sockaddr_in));
2103        }
2104        else
2105        {
2106            netmask_addr = NULL;
2107        }
2108
2109        if (broadcast_addr_vec != NULL && (if_flags & IFF_BROADCAST))
2110        {
2111            memcpy(&ifreq, ifr, sizeof(ifreq));
2112
2113            while (ioctl(lrpc->fd, SIOCGIFBRDADDR, &ifreq) == -1)
2114            {
2115                if (errno != EINTR)
2116                {
2117                    err = errno;
2118                    goto FREE_IT;
2119                }
2120            }
2121
2122            RPC_MEM_ALLOC (
2123                broadcast_addr,
2124                rpc_ip_addr_p_t,
2125                sizeof (rpc_ip_addr_t),
2126                RPC_C_MEM_RPC_ADDR,
2127                RPC_C_MEM_WAITOK);
2128
2129            if (broadcast_addr == NULL)
2130            {
2131                err = ENOMEM;
2132                goto FREE_IT;
2133            }
2134
2135            broadcast_addr->rpc_protseq_id = sock->pseq_id;
2136            broadcast_addr->len            = sizeof (struct sockaddr_in);
2137            memcpy(&broadcast_addr->sa, &ifreq.ifr_broadaddr, sizeof(struct sockaddr_in));
2138        }
2139        else
2140        {
2141            broadcast_addr = NULL;
2142        }
2143
2144        /*
2145         * Call out to do any final filtering and get the desired IP address
2146         * for this interface.  If the callout function returns false, we
2147         * forget about this interface.
2148         */
2149        if ((*efun) (sock, (rpc_addr_p_t) ip_addr, (rpc_addr_p_t) netmask_addr, (rpc_addr_p_t) broadcast_addr) == false)
2150        {
2151            if (ip_addr != NULL)
2152            {
2153                RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR);
2154                ip_addr = NULL;
2155            }
2156            if (netmask_addr != NULL)
2157            {
2158                RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR);
2159                netmask_addr = NULL;
2160            }
2161            if (broadcast_addr != NULL)
2162            {
2163                RPC_MEM_FREE (broadcast_addr, RPC_C_MEM_RPC_ADDR);
2164                broadcast_addr = NULL;
2165            }
2166            continue;
2167        }
2168
2169        if (rpc_addr_vec != NULL && ip_addr != NULL)
2170        {
2171            (*rpc_addr_vec)->addrs[(*rpc_addr_vec)->len++]
2172                = (rpc_addr_p_t) ip_addr;
2173            ip_addr = NULL;
2174        }
2175        if (netmask_addr_vec != NULL && netmask_addr != NULL)
2176        {
2177            (*netmask_addr_vec)->addrs[(*netmask_addr_vec)->len++]
2178                = (rpc_addr_p_t) netmask_addr;
2179            netmask_addr = NULL;
2180        }
2181        if (broadcast_addr_vec != NULL && broadcast_addr != NULL)
2182        {
2183            (*broadcast_addr_vec)->addrs[(*broadcast_addr_vec)->len++]
2184                = (rpc_addr_p_t) broadcast_addr;
2185            broadcast_addr = NULL;
2186        }
2187    }
2188
2189    if ((*rpc_addr_vec)->len == 0)
2190    {
2191        err = EINVAL;   /* !!! */
2192        goto FREE_IT;
2193    }
2194
2195    err = RPC_C_SOCKET_OK;
2196done:
2197
2198    return err;
2199
2200FREE_IT:
2201
2202    if (ip_addr != NULL)
2203    {
2204        RPC_MEM_FREE (ip_addr, RPC_C_MEM_RPC_ADDR);
2205    }
2206    if (netmask_addr != NULL)
2207    {
2208        RPC_MEM_FREE (netmask_addr, RPC_C_MEM_RPC_ADDR);
2209    }
2210    if (broadcast_addr != NULL)
2211    {
2212        RPC_MEM_FREE (broadcast_addr, RPC_C_MEM_RPC_ADDR);
2213    }
2214
2215    if (rpc_addr_vec != NULL && *rpc_addr_vec != NULL)
2216    {
2217        for (i = 0; i < (*rpc_addr_vec)->len; i++)
2218        {
2219            RPC_MEM_FREE ((*rpc_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR);
2220        }
2221        RPC_MEM_FREE (*rpc_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
2222        *rpc_addr_vec = NULL;
2223    }
2224    if (netmask_addr_vec != NULL && *netmask_addr_vec != NULL)
2225    {
2226        for (i = 0; i < (*netmask_addr_vec)->len; i++)
2227        {
2228            RPC_MEM_FREE ((*netmask_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR);
2229        }
2230        RPC_MEM_FREE (*netmask_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
2231        *netmask_addr_vec = NULL;
2232    }
2233    if (broadcast_addr_vec != NULL && *broadcast_addr_vec != NULL)
2234    {
2235        assert(broadcast_addr_vec != NULL);
2236        for (i = 0; i < (*broadcast_addr_vec)->len; i++)
2237        {
2238            RPC_MEM_FREE ((*broadcast_addr_vec)->addrs[i], RPC_C_MEM_RPC_ADDR);
2239        }
2240        RPC_MEM_FREE (*broadcast_addr_vec, RPC_C_MEM_RPC_ADDR_VEC);
2241        *broadcast_addr_vec = NULL;
2242    }
2243
2244    goto done;
2245}
2246
2247INTERNAL
2248rpc_socket_error_t
2249rpc__bsd_socket_inq_transport_info(
2250    rpc_socket_t sock ATTRIBUTE_UNUSED,
2251    rpc_transport_info_handle_t* info
2252    )
2253{
2254    rpc_socket_error_t serr = RPC_C_SOCKET_OK;
2255    rpc_bsd_socket_p_t lrpc = (rpc_bsd_socket_p_t) sock->data.pointer;
2256    rpc_bsd_transport_info_p_t lrpc_info = NULL;
2257
2258    lrpc_info = calloc(1, sizeof(*lrpc_info));
2259
2260    if (!lrpc_info)
2261    {
2262        serr = ENOMEM;
2263	goto error;
2264    }
2265
2266    lrpc_info->peer_uid = lrpc->info.peer_uid;
2267    lrpc_info->peer_gid = lrpc->info.peer_gid;
2268
2269    *info = (rpc_transport_info_handle_t) lrpc_info;
2270
2271error:
2272    if (serr)
2273    {
2274        *info = NULL;
2275
2276	if (lrpc_info)
2277        {
2278            rpc_lrpc_transport_info_free((rpc_transport_info_handle_t) lrpc_info);
2279        }
2280    }
2281
2282    return serr;
2283}
2284
2285void
2286rpc_lrpc_transport_info_free(
2287    rpc_transport_info_handle_t info
2288    )
2289{
2290    if (info)
2291    {
2292        free(info);
2293    }
2294}
2295
2296void
2297rpc_lrpc_transport_info_inq_peer_eid(
2298    rpc_transport_info_handle_t info,
2299    unsigned32                  *uid,
2300    unsigned32                  *gid
2301    )
2302{
2303    rpc_bsd_transport_info_p_t lrpc_info = (rpc_bsd_transport_info_p_t) info;
2304
2305    if (uid)
2306    {
2307        *uid = lrpc_info->peer_uid;
2308    }
2309
2310    if (gid)
2311    {
2312        *gid = lrpc_info->peer_gid;
2313    }
2314}
2315
2316INTERNAL
2317boolean
2318rpc__bsd_socket_transport_info_equal(
2319    rpc_transport_info_handle_t info1,
2320    rpc_transport_info_handle_t info2
2321    )
2322{
2323    rpc_bsd_transport_info_p_t bsd_info1 = (rpc_bsd_transport_info_p_t) info1;
2324    rpc_bsd_transport_info_p_t bsd_info2 = (rpc_bsd_transport_info_p_t) info2;
2325
2326    if ((bsd_info1 != NULL) && (bsd_info2 != NULL))
2327    {
2328        return
2329            (bsd_info1->peer_uid == bsd_info2->peer_uid &&
2330             bsd_info1->peer_gid == bsd_info2->peer_gid);
2331    } else if (bsd_info1 == bsd_info2){
2332        return true;
2333    }
2334
2335    rpc_bsd_transport_info_p_t tmp = bsd_info1 != NULL ? bsd_info1: bsd_info2;
2336    return  (tmp->peer_uid == getuid() && tmp->peer_gid == getgid());
2337}
2338
2339INTERNAL
2340rpc_socket_error_t
2341rpc__bsd_socket_transport_inq_access_token(
2342    rpc_transport_info_handle_t info ATTRIBUTE_UNUSED,
2343    rpc_access_token_p_t* token ATTRIBUTE_UNUSED
2344    )
2345{
2346#if HAVE_LIKEWISE_LWMAPSECURITY
2347    rpc_bsd_transport_info_p_t lrpc_info = (rpc_bsd_transport_info_p_t) info;
2348    NTSTATUS status = STATUS_SUCCESS;
2349    PLW_MAP_SECURITY_CONTEXT context = NULL;
2350
2351    status = LwMapSecurityCreateContext(&context);
2352    if (status) goto error;
2353
2354    status = LwMapSecurityCreateAccessTokenFromUidGid(
2355        context,
2356        token,
2357        lrpc_info->peer_uid,
2358        lrpc_info->peer_gid);
2359    if (status) goto error;
2360
2361error:
2362
2363    LwMapSecurityFreeContext(&context);
2364
2365    return LwNtStatusToErrno(status);
2366#else
2367    return RPC_C_SOCKET_ENOTSUP;
2368#endif
2369}
2370
2371PRIVATE const rpc_socket_vtbl_t rpc_g_bsd_socket_vtbl =
2372{
2373    .socket_duplicate = rpc__bsd_socket_duplicate,
2374    .socket_construct = rpc__bsd_socket_construct,
2375    .socket_destruct = rpc__bsd_socket_destruct,
2376    .socket_bind = rpc__bsd_socket_bind,
2377    .socket_connect = rpc__bsd_socket_connect,
2378    .socket_accept = rpc__bsd_socket_accept,
2379    .socket_listen = rpc__bsd_socket_listen,
2380    .socket_sendmsg = rpc__bsd_socket_sendmsg,
2381    .socket_recvfrom = rpc__bsd_socket_recvfrom,
2382    .socket_recvmsg = rpc__bsd_socket_recvmsg,
2383    .socket_inq_endpoint = rpc__bsd_socket_inq_endpoint,
2384    .socket_set_broadcast = rpc__bsd_socket_set_broadcast,
2385    .socket_set_bufs = rpc__bsd_socket_set_bufs,
2386    .socket_set_nbio = rpc__bsd_socket_set_nbio,
2387    .socket_set_close_on_exec = rpc__bsd_socket_set_close_on_exec,
2388    .socket_getpeername = rpc__bsd_socket_getpeername,
2389    .socket_get_if_id = rpc__bsd_socket_get_if_id,
2390    .socket_set_keepalive = rpc__bsd_socket_set_keepalive,
2391    .socket_nowriteblock_wait = rpc__bsd_socket_nowriteblock_wait,
2392    .socket_set_rcvtimeo = rpc__bsd_socket_set_rcvtimeo,
2393    .socket_getpeereid = rpc__bsd_socket_getpeereid,
2394    .socket_get_select_desc = rpc__bsd_socket_get_select_desc,
2395    .socket_enum_ifaces = rpc__bsd_socket_enum_ifaces,
2396    .socket_inq_transport_info = rpc__bsd_socket_inq_transport_info,
2397    .transport_info_free = rpc_lrpc_transport_info_free,
2398    .transport_info_equal = rpc__bsd_socket_transport_info_equal,
2399    .transport_inq_access_token = rpc__bsd_socket_transport_inq_access_token
2400};
2401