1 /* $NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $ */
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
27 * Sun Microsystems, Inc.
29 * Mountain View, California 94043
32 /* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
35 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
36 * In addition, portions of such source code were derived from Berkeley
37 * 4.3 BSD under license from the Regents of the University of
41 #include <sys/cdefs.h>
42 #if defined(LIBC_SCCS) && !defined(lint)
44 static char sccsid
[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
46 __RCSID("$NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $");
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
60 #include "namespace.h"
61 #include "reentrant.h"
62 #include <sys/types.h>
63 #include <sys/socket.h>
66 #include <rpc/pmap_clnt.h>
67 #include <rpc/pmap_prot.h>
68 #include <rpc/nettype.h>
69 #include <netinet/in.h>
78 #include "rpc_internal.h"
81 __weak_alias(clntudp_bufcreate
,_clntudp_bufcreate
)
82 __weak_alias(clntudp_create
,_clntudp_create
)
83 __weak_alias(clnttcp_create
,_clnttcp_create
)
84 __weak_alias(clntraw_create
,_clntraw_create
)
85 __weak_alias(get_myaddress
,_get_myaddress
)
86 __weak_alias(svcfd_create
,_svcfd_create
)
87 __weak_alias(svcudp_bufcreate
,_svcudp_bufcreate
)
88 __weak_alias(svcudp_create
,_svcudp_create
)
89 __weak_alias(svctcp_create
,_svctcp_create
)
90 __weak_alias(svcraw_create
,_svcraw_create
)
91 __weak_alias(callrpc
,_callrpc
)
92 __weak_alias(registerrpc
,_registerrpc
)
93 __weak_alias(clnt_broadcast
,_clnt_broadcast
)
97 extern mutex_t rpcsoc_lock
;
100 static CLIENT
*clnt_com_create
__P((struct sockaddr_in
*, rpcprog_t
, rpcvers_t
,
101 int *, u_int
, u_int
, const char *));
102 static SVCXPRT
*svc_com_create
__P((int, u_int
, u_int
, const char *));
103 static bool_t rpc_wrap_bcast
__P((char *, struct netbuf
*, struct netconfig
*));
106 * A common clnt create routine
109 clnt_com_create(raddr
, prog
, vers
, sockp
, sendsz
, recvsz
, tp
)
110 struct sockaddr_in
*raddr
;
121 struct netconfig
*nconf
;
122 struct netbuf bindaddr
;
124 _DIAGASSERT(raddr
!= NULL
);
125 _DIAGASSERT(sockp
!= NULL
);
126 _DIAGASSERT(tp
!= NULL
);
130 mutex_lock(&rpcsoc_lock
);
131 if ((nconf
= __rpc_getconfip(tp
)) == NULL
) {
132 rpc_createerr
.cf_stat
= RPC_UNKNOWNPROTO
;
133 mutex_unlock(&rpcsoc_lock
);
136 if (fd
== RPC_ANYSOCK
) {
137 fd
= __rpc_nconf2fd(nconf
);
143 if (raddr
->sin_port
== 0) {
147 mutex_unlock(&rpcsoc_lock
); /* pmap_getport is recursive */
148 proto
= strcmp(tp
, "udp") == 0 ? IPPROTO_UDP
: IPPROTO_TCP
;
149 sport
= pmap_getport(raddr
, (u_long
)prog
, (u_long
)vers
,
154 raddr
->sin_port
= htons(sport
);
155 mutex_lock(&rpcsoc_lock
); /* pmap_getport is recursive */
158 /* Transform sockaddr_in to netbuf */
159 bindaddr
.maxlen
= bindaddr
.len
= sizeof (struct sockaddr_in
);
160 bindaddr
.buf
= raddr
;
162 bindresvport(fd
, NULL
);
163 cl
= clnt_tli_create(fd
, nconf
, &bindaddr
, prog
, vers
,
166 if (madefd
== TRUE
) {
168 * The fd should be closed while destroying the handle.
170 (void) CLNT_CONTROL(cl
, CLSET_FD_CLOSE
, NULL
);
173 (void) freenetconfigent(nconf
);
174 mutex_unlock(&rpcsoc_lock
);
180 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
181 rpc_createerr
.cf_error
.re_errno
= errno
;
183 err
: if (madefd
== TRUE
)
185 (void) freenetconfigent(nconf
);
186 mutex_unlock(&rpcsoc_lock
);
191 clntudp_bufcreate(raddr
, prog
, vers
, wait
, sockp
, sendsz
, recvsz
)
192 struct sockaddr_in
*raddr
;
202 _DIAGASSERT(raddr
!= NULL
);
203 _DIAGASSERT(sockp
!= NULL
);
205 cl
= clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
206 sendsz
, recvsz
, "udp");
210 (void) CLNT_CONTROL(cl
, CLSET_RETRY_TIMEOUT
, (char *)(void *)&wait
);
215 clntudp_create(raddr
, program
, version
, wait
, sockp
)
216 struct sockaddr_in
*raddr
;
222 return clntudp_bufcreate(raddr
, program
, version
, wait
, sockp
,
223 UDPMSGSIZE
, UDPMSGSIZE
);
227 clnttcp_create(raddr
, prog
, vers
, sockp
, sendsz
, recvsz
)
228 struct sockaddr_in
*raddr
;
235 return clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
236 sendsz
, recvsz
, "tcp");
240 clntraw_create(prog
, vers
)
244 return clnt_raw_create((rpcprog_t
)prog
, (rpcvers_t
)vers
);
248 * A common server create routine
251 svc_com_create(fd
, sendsize
, recvsize
, netid
)
257 struct netconfig
*nconf
;
261 struct sockaddr_in sccsin
;
263 _DIAGASSERT(netid
!= NULL
);
265 if ((nconf
= __rpc_getconfip(netid
)) == NULL
) {
266 (void) syslog(LOG_ERR
, "Could not get %s transport", netid
);
269 if (fd
== RPC_ANYSOCK
) {
270 fd
= __rpc_nconf2fd(nconf
);
272 (void) freenetconfigent(nconf
);
273 (void) syslog(LOG_ERR
,
274 "svc%s_create: could not open connection", netid
);
280 memset(&sccsin
, 0, sizeof sccsin
);
281 sccsin
.sin_family
= AF_INET
;
282 bindresvport(fd
, &sccsin
);
283 listen(fd
, SOMAXCONN
);
284 svc
= svc_tli_create(fd
, nconf
, NULL
, sendsize
, recvsize
);
285 (void) freenetconfigent(nconf
);
291 port
= (((struct sockaddr_in
*)svc
->xp_ltaddr
.buf
)->sin_port
);
292 svc
->xp_port
= ntohs(port
);
297 svctcp_create(fd
, sendsize
, recvsize
)
302 return svc_com_create(fd
, sendsize
, recvsize
, "tcp");
306 svcudp_bufcreate(fd
, sendsz
, recvsz
)
308 u_int sendsz
, recvsz
;
310 return svc_com_create(fd
, sendsz
, recvsz
, "udp");
314 svcfd_create(fd
, sendsize
, recvsize
)
319 return svc_fd_create(fd
, sendsize
, recvsize
);
327 return svc_com_create(fd
, UDPMSGSIZE
, UDPMSGSIZE
, "udp");
333 return svc_raw_create();
338 struct sockaddr_in
*addr
;
341 _DIAGASSERT(addr
!= NULL
);
343 memset((void *) addr
, 0, sizeof(*addr
));
344 addr
->sin_family
= AF_INET
;
345 addr
->sin_port
= htons(PMAPPORT
);
346 addr
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
351 * For connectionless "udp" transport. Obsoleted by rpc_call().
354 callrpc(host
, prognum
, versnum
, procnum
, inproc
, in
, outproc
, out
)
356 int prognum
, versnum
, procnum
;
357 xdrproc_t inproc
, outproc
;
360 return (int)rpc_call(host
, (rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
361 (rpcproc_t
)procnum
, inproc
, in
, outproc
, out
, "udp");
365 * For connectionless kind of transport. Obsoleted by rpc_reg()
368 registerrpc(prognum
, versnum
, procnum
, progname
, inproc
, outproc
)
369 int prognum
, versnum
, procnum
;
370 char *(*progname
) __P((char [UDPMSGSIZE
]));
371 xdrproc_t inproc
, outproc
;
373 return rpc_reg((rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
374 (rpcproc_t
)procnum
, progname
, inproc
, outproc
, __UNCONST("udp"));
378 * All the following clnt_broadcast stuff is convulated; it supports
379 * the earlier calling style of the callback function
382 static thread_key_t clnt_broadcast_key
;
384 static resultproc_t clnt_broadcast_result_main
;
387 * Need to translate the netbuf address into sockaddr_in address.
388 * Dont care about netid here.
392 rpc_wrap_bcast(resultp
, addr
, nconf
)
393 char *resultp
; /* results of the call */
394 struct netbuf
*addr
; /* address of the guy who responded */
395 struct netconfig
*nconf
; /* Netconf of the transport */
397 resultproc_t clnt_broadcast_result
;
399 _DIAGASSERT(resultp
!= NULL
);
400 _DIAGASSERT(addr
!= NULL
);
401 _DIAGASSERT(nconf
!= NULL
);
403 if (strcmp(nconf
->nc_netid
, "udp"))
406 if (__isthreaded
== 0)
407 clnt_broadcast_result
= clnt_broadcast_result_main
;
409 clnt_broadcast_result
= thr_getspecific(clnt_broadcast_key
);
411 clnt_broadcast_result
= clnt_broadcast_result_main
;
413 return (*clnt_broadcast_result
)(resultp
,
414 (struct sockaddr_in
*)addr
->buf
);
418 static once_t clnt_broadcast_once
= ONCE_INITIALIZER
;
421 clnt_broadcast_setup(void)
424 thr_keycreate(&clnt_broadcast_key
, free
);
429 * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
432 clnt_broadcast(prog
, vers
, proc
, xargs
, argsp
, xresults
, resultsp
, eachresult
)
433 u_long prog
; /* program number */
434 u_long vers
; /* version number */
435 u_long proc
; /* procedure number */
436 xdrproc_t xargs
; /* xdr routine for args */
437 caddr_t argsp
; /* pointer to args */
438 xdrproc_t xresults
; /* xdr routine for results */
439 caddr_t resultsp
; /* pointer to results */
440 resultproc_t eachresult
; /* call with each result obtained */
443 if (__isthreaded
== 0)
444 clnt_broadcast_result_main
= eachresult
;
446 thr_once(&clnt_broadcast_once
, clnt_broadcast_setup
);
447 thr_setspecific(clnt_broadcast_key
, (void *) eachresult
);
450 clnt_broadcast_result_main
= eachresult
;
452 return rpc_broadcast((rpcprog_t
)prog
, (rpcvers_t
)vers
,
453 (rpcproc_t
)proc
, xargs
, argsp
, xresults
, resultsp
,
454 (resultproc_t
) rpc_wrap_bcast
, "udp");