source: rtems-libbsd/freebsd/lib/libc/rpc/rpc_soc.c

6-freebsd-12
Last change on this file was bb80d9d, checked in by Sebastian Huber <sebastian.huber@…>, on 08/09/18 at 12:02:09

Update to FreeBSD head 2017-12-01

Git mirror commit e724f51f811a4b2bd29447f8b85ab5c2f9b88266.

Update #3472.

  • Property mode set to 100644
File size: 13.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*      $NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $     */
4
5/*-
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 * Copyright (c) 2009, Sun Microsystems, Inc.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 *   this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 *   this list of conditions and the following disclaimer in the documentation
17 *   and/or other materials provided with the distribution.
18 * - Neither the name of Sun Microsystems, Inc. nor the names of its
19 *   contributors may be used to endorse or promote products derived
20 *   from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35/* #ident       "@(#)rpc_soc.c  1.17    94/04/24 SMI" */
36
37/*
38 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
39 * In addition, portions of such source code were derived from Berkeley
40 * 4.3 BSD under license from the Regents of the University of
41 * California.
42 */
43
44#if defined(LIBC_SCCS) && !defined(lint)
45static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
46#endif
47#include <sys/cdefs.h>
48__FBSDID("$FreeBSD$");
49
50#ifdef PORTMAP
51/*
52 * rpc_soc.c
53 *
54 * The backward compatibility routines for the earlier implementation
55 * of RPC, where the only transports supported were tcp/ip and udp/ip.
56 * Based on berkeley socket abstraction, now implemented on the top
57 * of TLI/Streams
58 */
59
60#include "namespace.h"
61#include "reentrant.h"
62#include <sys/types.h>
63#include <sys/socket.h>
64#include <stdio.h>
65#include <rpc/rpc.h>
66#include <rpc/pmap_clnt.h>
67#include <rpc/pmap_prot.h>
68#include <rpc/nettype.h>
69#include <syslog.h>
70#include <netinet/in.h>
71#include <netdb.h>
72#include <errno.h>
73#include <syslog.h>
74#include <stdlib.h>
75#include <string.h>
76#include <unistd.h>
77#include "un-namespace.h"
78
79#include "rpc_com.h"
80#include "mt_misc.h"
81
82static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
83    int *, u_int, u_int, char *);
84static SVCXPRT *svc_com_create(int, u_int, u_int, char *);
85static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
86
87/* XXX */
88#define IN4_LOCALHOST_STRING    "127.0.0.1"
89#define IN6_LOCALHOST_STRING    "::1"
90
91/*
92 * A common clnt create routine
93 */
94static CLIENT *
95clnt_com_create(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, int *sockp,
96    u_int sendsz, u_int recvsz, char *tp)
97{
98        CLIENT *cl;
99        int madefd = FALSE;
100        int fd = *sockp;
101        struct netconfig *nconf;
102        struct netbuf bindaddr;
103
104        mutex_lock(&rpcsoc_lock);
105        if ((nconf = __rpc_getconfip(tp)) == NULL) {
106                rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
107                mutex_unlock(&rpcsoc_lock);
108                return (NULL);
109        }
110        if (fd == RPC_ANYSOCK) {
111                fd = __rpc_nconf2fd(nconf);
112                if (fd == -1)
113                        goto syserror;
114                madefd = TRUE;
115        }
116
117        if (raddr->sin_port == 0) {
118                u_int proto;
119                u_short sport;
120
121                mutex_unlock(&rpcsoc_lock);     /* pmap_getport is recursive */
122                proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
123                sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
124                    proto);
125                if (sport == 0) {
126                        goto err;
127                }
128                raddr->sin_port = htons(sport);
129                mutex_lock(&rpcsoc_lock);       /* pmap_getport is recursive */
130        }
131
132        /* Transform sockaddr_in to netbuf */
133        bindaddr.maxlen = bindaddr.len =  sizeof (struct sockaddr_in);
134        bindaddr.buf = raddr;
135
136        bindresvport(fd, NULL);
137        cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
138                                sendsz, recvsz);
139        if (cl) {
140                if (madefd == TRUE) {
141                        /*
142                         * The fd should be closed while destroying the handle.
143                         */
144                        (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
145                        *sockp = fd;
146                }
147                (void) freenetconfigent(nconf);
148                mutex_unlock(&rpcsoc_lock);
149                return (cl);
150        }
151        goto err;
152
153syserror:
154        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
155        rpc_createerr.cf_error.re_errno = errno;
156
157err:    if (madefd == TRUE)
158                (void)_close(fd);
159        (void) freenetconfigent(nconf);
160        mutex_unlock(&rpcsoc_lock);
161        return (NULL);
162}
163
164CLIENT *
165clntudp_bufcreate(struct sockaddr_in *raddr, u_long prog, u_long vers,
166    struct timeval wait, int *sockp, u_int sendsz, u_int recvsz)
167{
168        CLIENT *cl;
169
170        cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
171            sendsz, recvsz, "udp");
172        if (cl == NULL) {
173                return (NULL);
174        }
175        (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
176        return (cl);
177}
178
179CLIENT *
180clntudp_create(struct sockaddr_in *raddr, u_long program, u_long version,
181    struct timeval wait, int *sockp)
182{
183
184        return clntudp_bufcreate(raddr, program, version, wait, sockp,
185                                        UDPMSGSIZE, UDPMSGSIZE);
186}
187
188CLIENT *
189clnttcp_create(struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp,
190    u_int sendsz, u_int recvsz)
191{
192
193        return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
194            sendsz, recvsz, "tcp");
195}
196
197CLIENT *
198clntraw_create(u_long prog, u_long vers)
199{
200
201        return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
202}
203
204/*
205 * A common server create routine
206 */
207static SVCXPRT *
208svc_com_create(int fd, u_int sendsize, u_int recvsize, char *netid)
209{
210        struct netconfig *nconf;
211        SVCXPRT *svc;
212        int madefd = FALSE;
213        int port;
214        struct sockaddr_in sin;
215
216        if ((nconf = __rpc_getconfip(netid)) == NULL) {
217                (void) syslog(LOG_ERR, "Could not get %s transport", netid);
218                return (NULL);
219        }
220        if (fd == RPC_ANYSOCK) {
221                fd = __rpc_nconf2fd(nconf);
222                if (fd == -1) {
223                        (void) freenetconfigent(nconf);
224                        (void) syslog(LOG_ERR,
225                        "svc%s_create: could not open connection", netid);
226                        return (NULL);
227                }
228                madefd = TRUE;
229        }
230
231        memset(&sin, 0, sizeof sin);
232        sin.sin_family = AF_INET;
233        bindresvport(fd, &sin);
234        _listen(fd, SOMAXCONN);
235        svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
236        (void) freenetconfigent(nconf);
237        if (svc == NULL) {
238                if (madefd)
239                        (void)_close(fd);
240                return (NULL);
241        }
242        port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
243        svc->xp_port = ntohs(port);
244        return (svc);
245}
246
247SVCXPRT *
248svctcp_create(int fd, u_int sendsize, u_int recvsize)
249{
250
251        return svc_com_create(fd, sendsize, recvsize, "tcp");
252}
253
254SVCXPRT *
255svcudp_bufcreate(int fd, u_int sendsz, u_int recvsz)
256{
257
258        return svc_com_create(fd, sendsz, recvsz, "udp");
259}
260
261SVCXPRT *
262svcfd_create(int fd, u_int sendsize, u_int recvsize)
263{
264
265        return svc_fd_create(fd, sendsize, recvsize);
266}
267
268
269SVCXPRT *
270svcudp_create(int fd)
271{
272
273        return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
274}
275
276SVCXPRT *
277svcraw_create(void)
278{
279
280        return svc_raw_create();
281}
282
283int
284get_myaddress(struct sockaddr_in *addr)
285{
286
287        memset((void *) addr, 0, sizeof(*addr));
288        addr->sin_family = AF_INET;
289        addr->sin_port = htons(PMAPPORT);
290        addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
291        return (0);
292}
293
294/*
295 * For connectionless "udp" transport. Obsoleted by rpc_call().
296 */
297int
298callrpc(const char *host, int prognum, int versnum, int procnum,
299    xdrproc_t inproc, void *in, xdrproc_t outproc, void *out)
300{
301
302        return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
303            (rpcproc_t)procnum, inproc, in, outproc, out, "udp");
304}
305
306/*
307 * For connectionless kind of transport. Obsoleted by rpc_reg()
308 */
309int
310registerrpc(int prognum, int versnum, int procnum,
311    char *(*progname)(char [UDPMSGSIZE]),
312    xdrproc_t inproc, xdrproc_t outproc)
313{
314
315        return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
316            (rpcproc_t)procnum, progname, inproc, outproc, "udp");
317}
318
319/*
320 * All the following clnt_broadcast stuff is convulated; it supports
321 * the earlier calling style of the callback function
322 */
323static thread_key_t     clnt_broadcast_key;
324static resultproc_t     clnt_broadcast_result_main;
325static once_t           clnt_broadcast_once = ONCE_INITIALIZER;
326
327static void
328clnt_broadcast_key_init(void)
329{
330
331        thr_keycreate(&clnt_broadcast_key, free);
332}
333
334/*
335 * Need to translate the netbuf address into sockaddr_in address.
336 * Dont care about netid here.
337 */
338/* ARGSUSED */
339static bool_t
340rpc_wrap_bcast(char *resultp, struct netbuf *addr, struct netconfig *nconf)
341/*
342 *      char *resultp;          // results of the call
343 *      struct netbuf *addr;    // address of the guy who responded
344 *      struct netconfig *nconf; // Netconf of the transport
345 */
346{
347        resultproc_t clnt_broadcast_result;
348
349        if (strcmp(nconf->nc_netid, "udp"))
350                return (FALSE);
351        if (thr_main())
352                clnt_broadcast_result = clnt_broadcast_result_main;
353        else
354                clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
355        return (*clnt_broadcast_result)(resultp,
356                                (struct sockaddr_in *)addr->buf);
357}
358
359/*
360 * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
361 */
362enum clnt_stat
363clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs,
364    void *argsp, xdrproc_t xresults, void *resultsp, resultproc_t eachresult)
365/*
366 *      u_long          prog;           // program number
367 *      u_long          vers;           // version number
368 *      u_long          proc;           // procedure number
369 *      xdrproc_t       xargs;          // xdr routine for args
370 *      void           *argsp;          // pointer to args
371 *      xdrproc_t       xresults;       // xdr routine for results
372 *      void           *resultsp;       // pointer to results
373 *      resultproc_t    eachresult;     // call with each result obtained
374 */
375{
376
377        if (thr_main())
378                clnt_broadcast_result_main = eachresult;
379        else {
380                thr_once(&clnt_broadcast_once, clnt_broadcast_key_init);
381                thr_setspecific(clnt_broadcast_key, (void *) eachresult);
382        }
383        return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
384            (rpcproc_t)proc, xargs, argsp, xresults, resultsp,
385            (resultproc_t) rpc_wrap_bcast, "udp");
386}
387
388/*
389 * Create the client des authentication object. Obsoleted by
390 * authdes_seccreate().
391 */
392AUTH *
393authdes_create(char *servername, u_int window, struct sockaddr *syncaddr,
394    des_block *ckey)
395/*
396 *      char *servername;               // network name of server
397 *      u_int window;                   // time to live
398 *      struct sockaddr *syncaddr;      // optional hostaddr to sync with
399 *      des_block *ckey;                // optional conversation key to use
400 */
401{
402        AUTH *dummy;
403        AUTH *nauth;
404        char hostname[NI_MAXHOST];
405
406        if (syncaddr) {
407                /*
408                 * Change addr to hostname, because that is the way
409                 * new interface takes it.
410                 */
411                if (getnameinfo(syncaddr, syncaddr->sa_len, hostname,
412                    sizeof hostname, NULL, 0, 0) != 0)
413                        goto fallback;
414
415                nauth = authdes_seccreate(servername, window, hostname, ckey);
416                return (nauth);
417        }
418fallback:
419        dummy = authdes_seccreate(servername, window, NULL, ckey);
420        return (dummy);
421}
422
423/*
424 * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
425 */
426CLIENT *
427clntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp,
428    u_int sendsz, u_int recvsz)
429{
430        struct netbuf *svcaddr;
431        CLIENT *cl;
432        int len;
433
434        cl = NULL;
435        svcaddr = NULL;
436        if ((raddr->sun_len == 0) ||
437           ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
438           ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
439                free(svcaddr);
440                rpc_createerr.cf_stat = RPC_SYSTEMERROR;
441                rpc_createerr.cf_error.re_errno = errno;
442                return(cl);
443        }
444        if (*sockp < 0) {
445                *sockp = _socket(AF_LOCAL, SOCK_STREAM, 0);
446                len = raddr->sun_len = SUN_LEN(raddr);
447                if ((*sockp < 0) || (_connect(*sockp,
448                    (struct sockaddr *)raddr, len) < 0)) {
449                        rpc_createerr.cf_stat = RPC_SYSTEMERROR;
450                        rpc_createerr.cf_error.re_errno = errno;
451                        if (*sockp != -1)
452                                (void)_close(*sockp);
453                        goto done;
454                }
455        }
456        svcaddr->buf = raddr;
457        svcaddr->len = raddr->sun_len;
458        svcaddr->maxlen = sizeof (struct sockaddr_un);
459        cl = clnt_vc_create(*sockp, svcaddr, prog,
460            vers, sendsz, recvsz);
461done:
462        free(svcaddr->buf);
463        free(svcaddr);
464        return(cl);
465}
466
467/*
468 * Creates, registers, and returns a (rpc) unix based transporter.
469 * Obsoleted by svc_vc_create().
470 */
471SVCXPRT *
472svcunix_create(int sock, u_int sendsize, u_int recvsize, char *path)
473{
474        struct netconfig *nconf;
475        void *localhandle;
476        struct sockaddr_un sun;
477        struct sockaddr *sa;
478        struct t_bind taddr;
479        SVCXPRT *xprt;
480        int addrlen;
481
482        xprt = (SVCXPRT *)NULL;
483        localhandle = setnetconfig();
484        while ((nconf = getnetconfig(localhandle)) != NULL) {
485                if (nconf->nc_protofmly != NULL &&
486                    strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
487                        break;
488        }
489        if (nconf == NULL)
490                goto done;
491
492        if ((sock = __rpc_nconf2fd(nconf)) < 0)
493                goto done;
494
495        memset(&sun, 0, sizeof sun);
496        sun.sun_family = AF_LOCAL;
497        if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
498            sizeof(sun.sun_path))
499                goto done;
500        sun.sun_len = SUN_LEN(&sun);
501        addrlen = sizeof (struct sockaddr_un);
502        sa = (struct sockaddr *)&sun;
503
504        if (_bind(sock, sa, addrlen) < 0)
505                goto done;
506
507        taddr.addr.len = taddr.addr.maxlen = addrlen;
508        taddr.addr.buf = malloc(addrlen);
509        if (taddr.addr.buf == NULL)
510                goto done;
511        memcpy(taddr.addr.buf, sa, addrlen);
512
513        if (nconf->nc_semantics != NC_TPI_CLTS) {
514                if (_listen(sock, SOMAXCONN) < 0) {
515                        free(taddr.addr.buf);
516                        goto done;
517                }
518        }
519
520        xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);
521
522done:
523        endnetconfig(localhandle);
524        return(xprt);
525}
526
527/*
528 * Like svunix_create(), except the routine takes any *open* UNIX file
529 * descriptor as its first input. Obsoleted by svc_fd_create();
530 */
531SVCXPRT *
532svcunixfd_create(int fd, u_int sendsize, u_int recvsize)
533{
534        return (svc_fd_create(fd, sendsize, recvsize));
535}
536
537#endif /* PORTMAP */
Note: See TracBrowser for help on using the repository browser.