1 /* $NetBSD: rpc_soc.c,v 1.18 2013/03/11 20:19:29 tron Exp $ */
4 * Copyright (c) 2010, Oracle America, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 /* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
37 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
38 * In addition, portions of such source code were derived from Berkeley
39 * 4.3 BSD under license from the Regents of the University of
43 #include <sys/cdefs.h>
44 #if defined(LIBC_SCCS) && !defined(lint)
46 static char sccsid
[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
48 __RCSID("$NetBSD: rpc_soc.c,v 1.18 2013/03/11 20:19:29 tron Exp $");
56 * The backward compatibility routines for the earlier implementation
57 * of RPC, where the only transports supported were tcp/ip and udp/ip.
58 * Based on berkeley socket abstraction, now implemented on the top
62 #include "namespace.h"
63 #include "reentrant.h"
64 #include <sys/types.h>
65 #include <sys/socket.h>
68 #include <rpc/pmap_clnt.h>
69 #include <rpc/pmap_prot.h>
70 #include <rpc/nettype.h>
71 #include <netinet/in.h>
80 #include "svc_fdset.h"
81 #include "rpc_internal.h"
84 __weak_alias(clntudp_bufcreate
,_clntudp_bufcreate
)
85 __weak_alias(clntudp_create
,_clntudp_create
)
86 __weak_alias(clnttcp_create
,_clnttcp_create
)
87 __weak_alias(clntraw_create
,_clntraw_create
)
88 __weak_alias(get_myaddress
,_get_myaddress
)
89 __weak_alias(svcfd_create
,_svcfd_create
)
90 __weak_alias(svcudp_bufcreate
,_svcudp_bufcreate
)
91 __weak_alias(svcudp_create
,_svcudp_create
)
92 __weak_alias(svctcp_create
,_svctcp_create
)
93 __weak_alias(svcraw_create
,_svcraw_create
)
94 __weak_alias(callrpc
,_callrpc
)
95 __weak_alias(registerrpc
,_registerrpc
)
96 __weak_alias(clnt_broadcast
,_clnt_broadcast
)
100 extern mutex_t rpcsoc_lock
;
103 static CLIENT
*clnt_com_create(struct sockaddr_in
*, rpcprog_t
, rpcvers_t
,
104 int *, u_int
, u_int
, const char *);
105 static SVCXPRT
*svc_com_create(int, u_int
, u_int
, const char *);
106 static bool_t
rpc_wrap_bcast(char *, struct netbuf
*, struct netconfig
*);
109 * A common clnt create routine
112 clnt_com_create(struct sockaddr_in
*raddr
, rpcprog_t prog
, rpcvers_t vers
,
113 int *sockp
, u_int sendsz
, u_int recvsz
, const char *tp
)
118 struct netconfig
*nconf
;
119 struct netbuf bindaddr
;
121 _DIAGASSERT(raddr
!= NULL
);
122 _DIAGASSERT(sockp
!= NULL
);
123 _DIAGASSERT(tp
!= NULL
);
127 mutex_lock(&rpcsoc_lock
);
128 if ((nconf
= __rpc_getconfip(tp
)) == NULL
) {
129 rpc_createerr
.cf_stat
= RPC_UNKNOWNPROTO
;
130 mutex_unlock(&rpcsoc_lock
);
133 if (fd
== RPC_ANYSOCK
) {
134 fd
= __rpc_nconf2fd(nconf
);
140 if (raddr
->sin_port
== 0) {
144 mutex_unlock(&rpcsoc_lock
); /* pmap_getport is recursive */
145 proto
= strcmp(tp
, "udp") == 0 ? IPPROTO_UDP
: IPPROTO_TCP
;
146 sport
= pmap_getport(raddr
, (u_long
)prog
, (u_long
)vers
,
151 raddr
->sin_port
= htons(sport
);
152 mutex_lock(&rpcsoc_lock
); /* pmap_getport is recursive */
155 /* Transform sockaddr_in to netbuf */
156 bindaddr
.maxlen
= bindaddr
.len
= sizeof (struct sockaddr_in
);
157 bindaddr
.buf
= raddr
;
159 bindresvport(fd
, NULL
);
160 cl
= clnt_tli_create(fd
, nconf
, &bindaddr
, prog
, vers
,
163 if (madefd
== TRUE
) {
165 * The fd should be closed while destroying the handle.
167 (void) CLNT_CONTROL(cl
, CLSET_FD_CLOSE
, NULL
);
170 (void) freenetconfigent(nconf
);
171 mutex_unlock(&rpcsoc_lock
);
177 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
178 rpc_createerr
.cf_error
.re_errno
= errno
;
180 err
: if (madefd
== TRUE
)
182 (void) freenetconfigent(nconf
);
183 mutex_unlock(&rpcsoc_lock
);
188 clntudp_bufcreate(struct sockaddr_in
*raddr
, u_long prog
, u_long vers
, struct timeval wait
, int *sockp
, u_int sendsz
, u_int recvsz
)
192 _DIAGASSERT(raddr
!= NULL
);
193 _DIAGASSERT(sockp
!= NULL
);
195 cl
= clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
196 sendsz
, recvsz
, "udp");
200 (void) CLNT_CONTROL(cl
, CLSET_RETRY_TIMEOUT
, (char *)(void *)&wait
);
205 clntudp_create(struct sockaddr_in
*raddr
, u_long program
, u_long version
,
206 struct timeval wait
, int *sockp
)
208 return clntudp_bufcreate(raddr
, program
, version
, wait
, sockp
,
209 UDPMSGSIZE
, UDPMSGSIZE
);
213 clnttcp_create(struct sockaddr_in
*raddr
, u_long prog
, u_long vers
, int *sockp
,
214 u_int sendsz
, u_int recvsz
)
216 return clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
217 sendsz
, recvsz
, "tcp");
221 clntraw_create(u_long prog
, u_long vers
)
223 return clnt_raw_create((rpcprog_t
)prog
, (rpcvers_t
)vers
);
227 * A common server create routine
230 svc_com_create(int fd
, u_int sendsize
, u_int recvsize
, const char *netid
)
232 struct netconfig
*nconf
;
236 struct sockaddr_in sccsin
;
238 _DIAGASSERT(netid
!= NULL
);
240 if ((nconf
= __rpc_getconfip(netid
)) == NULL
) {
241 (void) syslog(LOG_ERR
, "Could not get %s transport", netid
);
244 if (fd
== RPC_ANYSOCK
) {
245 fd
= __rpc_nconf2fd(nconf
);
247 (void) freenetconfigent(nconf
);
248 (void) syslog(LOG_ERR
,
249 "svc%s_create: could not open connection", netid
);
255 memset(&sccsin
, 0, sizeof sccsin
);
256 sccsin
.sin_family
= AF_INET
;
257 bindresvport(fd
, &sccsin
);
258 listen(fd
, SOMAXCONN
);
259 svc
= svc_tli_create(fd
, nconf
, NULL
, sendsize
, recvsize
);
260 (void) freenetconfigent(nconf
);
266 port
= (((struct sockaddr_in
*)svc
->xp_ltaddr
.buf
)->sin_port
);
267 svc
->xp_port
= ntohs(port
);
272 svctcp_create(int fd
, u_int sendsize
, u_int recvsize
)
274 return svc_com_create(fd
, sendsize
, recvsize
, "tcp");
278 svcudp_bufcreate(int fd
, u_int sendsz
, u_int recvsz
)
280 return svc_com_create(fd
, sendsz
, recvsz
, "udp");
284 svcfd_create(int fd
, u_int sendsize
, u_int recvsize
)
286 return svc_fd_create(fd
, sendsize
, recvsize
);
291 svcudp_create(int fd
)
293 return svc_com_create(fd
, UDPMSGSIZE
, UDPMSGSIZE
, "udp");
299 return svc_raw_create();
303 get_myaddress(struct sockaddr_in
*addr
)
306 _DIAGASSERT(addr
!= NULL
);
308 memset((void *) addr
, 0, sizeof(*addr
));
309 addr
->sin_family
= AF_INET
;
310 addr
->sin_port
= htons(PMAPPORT
);
311 addr
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
316 * For connectionless "udp" transport. Obsoleted by rpc_call().
319 callrpc(char *host
, int prognum
, int versnum
, int procnum
,
320 xdrproc_t inproc
, char *in
, xdrproc_t outproc
, char *out
)
322 return (int)rpc_call(host
, (rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
323 (rpcproc_t
)procnum
, inproc
, in
, outproc
, out
, "udp");
327 * For connectionless kind of transport. Obsoleted by rpc_reg()
330 registerrpc(int prognum
, int versnum
, int procnum
,
331 char *(*progname
)(char [UDPMSGSIZE
]),
332 xdrproc_t inproc
, xdrproc_t outproc
)
334 return rpc_reg((rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
335 (rpcproc_t
)procnum
, progname
, inproc
, outproc
, __UNCONST("udp"));
339 * All the following clnt_broadcast stuff is convulated; it supports
340 * the earlier calling style of the callback function
343 static thread_key_t clnt_broadcast_key
;
345 static resultproc_t clnt_broadcast_result_main
;
348 * Need to translate the netbuf address into sockaddr_in address.
349 * Dont care about netid here.
354 char *resultp
, /* results of the call */
355 struct netbuf
*addr
, /* address of the guy who responded */
356 struct netconfig
*nconf
) /* Netconf of the transport */
358 resultproc_t clnt_broadcast_result
;
360 _DIAGASSERT(resultp
!= NULL
);
361 _DIAGASSERT(addr
!= NULL
);
362 _DIAGASSERT(nconf
!= NULL
);
364 if (strcmp(nconf
->nc_netid
, "udp"))
367 if (__isthreaded
== 0)
368 clnt_broadcast_result
= clnt_broadcast_result_main
;
370 clnt_broadcast_result
= thr_getspecific(clnt_broadcast_key
);
372 clnt_broadcast_result
= clnt_broadcast_result_main
;
374 return (*clnt_broadcast_result
)(resultp
,
375 (struct sockaddr_in
*)addr
->buf
);
379 static once_t clnt_broadcast_once
= ONCE_INITIALIZER
;
382 clnt_broadcast_setup(void)
385 thr_keycreate(&clnt_broadcast_key
, free
);
390 * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
394 u_long prog
, /* program number */
395 u_long vers
, /* version number */
396 u_long proc
, /* procedure number */
397 xdrproc_t xargs
, /* xdr routine for args */
398 caddr_t argsp
, /* pointer to args */
399 xdrproc_t xresults
, /* xdr routine for results */
400 caddr_t resultsp
, /* pointer to results */
401 resultproc_t eachresult
) /* call with each result obtained */
404 if (__isthreaded
== 0)
405 clnt_broadcast_result_main
= eachresult
;
407 thr_once(&clnt_broadcast_once
, clnt_broadcast_setup
);
408 thr_setspecific(clnt_broadcast_key
, (void *) eachresult
);
411 clnt_broadcast_result_main
= eachresult
;
413 return rpc_broadcast((rpcprog_t
)prog
, (rpcvers_t
)vers
,
414 (rpcproc_t
)proc
, xargs
, argsp
, xresults
, resultsp
,
415 (resultproc_t
) rpc_wrap_bcast
, "udp");