1 /* $NetBSD: rpc_soc.c,v 1.16 2012/06/25 22:32:45 abs 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.16 2012/06/25 22:32:45 abs 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(struct sockaddr_in
*, rpcprog_t
, rpcvers_t
,
101 int *, u_int
, u_int
, const char *);
102 static SVCXPRT
*svc_com_create(int, u_int
, u_int
, const char *);
103 static bool_t
rpc_wrap_bcast(char *, struct netbuf
*, struct netconfig
*);
106 * A common clnt create routine
109 clnt_com_create(struct sockaddr_in
*raddr
, rpcprog_t prog
, rpcvers_t vers
,
110 int *sockp
, u_int sendsz
, u_int recvsz
, const char *tp
)
115 struct netconfig
*nconf
;
116 struct netbuf bindaddr
;
118 _DIAGASSERT(raddr
!= NULL
);
119 _DIAGASSERT(sockp
!= NULL
);
120 _DIAGASSERT(tp
!= NULL
);
124 mutex_lock(&rpcsoc_lock
);
125 if ((nconf
= __rpc_getconfip(tp
)) == NULL
) {
126 rpc_createerr
.cf_stat
= RPC_UNKNOWNPROTO
;
127 mutex_unlock(&rpcsoc_lock
);
130 if (fd
== RPC_ANYSOCK
) {
131 fd
= __rpc_nconf2fd(nconf
);
137 if (raddr
->sin_port
== 0) {
141 mutex_unlock(&rpcsoc_lock
); /* pmap_getport is recursive */
142 proto
= strcmp(tp
, "udp") == 0 ? IPPROTO_UDP
: IPPROTO_TCP
;
143 sport
= pmap_getport(raddr
, (u_long
)prog
, (u_long
)vers
,
148 raddr
->sin_port
= htons(sport
);
149 mutex_lock(&rpcsoc_lock
); /* pmap_getport is recursive */
152 /* Transform sockaddr_in to netbuf */
153 bindaddr
.maxlen
= bindaddr
.len
= sizeof (struct sockaddr_in
);
154 bindaddr
.buf
= raddr
;
156 bindresvport(fd
, NULL
);
157 cl
= clnt_tli_create(fd
, nconf
, &bindaddr
, prog
, vers
,
160 if (madefd
== TRUE
) {
162 * The fd should be closed while destroying the handle.
164 (void) CLNT_CONTROL(cl
, CLSET_FD_CLOSE
, NULL
);
167 (void) freenetconfigent(nconf
);
168 mutex_unlock(&rpcsoc_lock
);
174 rpc_createerr
.cf_stat
= RPC_SYSTEMERROR
;
175 rpc_createerr
.cf_error
.re_errno
= errno
;
177 err
: if (madefd
== TRUE
)
179 (void) freenetconfigent(nconf
);
180 mutex_unlock(&rpcsoc_lock
);
185 clntudp_bufcreate(struct sockaddr_in
*raddr
, u_long prog
, u_long vers
, struct timeval wait
, int *sockp
, u_int sendsz
, u_int recvsz
)
189 _DIAGASSERT(raddr
!= NULL
);
190 _DIAGASSERT(sockp
!= NULL
);
192 cl
= clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
193 sendsz
, recvsz
, "udp");
197 (void) CLNT_CONTROL(cl
, CLSET_RETRY_TIMEOUT
, (char *)(void *)&wait
);
202 clntudp_create(struct sockaddr_in
*raddr
, u_long program
, u_long version
,
203 struct timeval wait
, int *sockp
)
205 return clntudp_bufcreate(raddr
, program
, version
, wait
, sockp
,
206 UDPMSGSIZE
, UDPMSGSIZE
);
210 clnttcp_create(struct sockaddr_in
*raddr
, u_long prog
, u_long vers
, int *sockp
,
211 u_int sendsz
, u_int recvsz
)
213 return clnt_com_create(raddr
, (rpcprog_t
)prog
, (rpcvers_t
)vers
, sockp
,
214 sendsz
, recvsz
, "tcp");
218 clntraw_create(u_long prog
, u_long vers
)
220 return clnt_raw_create((rpcprog_t
)prog
, (rpcvers_t
)vers
);
224 * A common server create routine
227 svc_com_create(int fd
, u_int sendsize
, u_int recvsize
, const char *netid
)
229 struct netconfig
*nconf
;
233 struct sockaddr_in sccsin
;
235 _DIAGASSERT(netid
!= NULL
);
237 if ((nconf
= __rpc_getconfip(netid
)) == NULL
) {
238 (void) syslog(LOG_ERR
, "Could not get %s transport", netid
);
241 if (fd
== RPC_ANYSOCK
) {
242 fd
= __rpc_nconf2fd(nconf
);
244 (void) freenetconfigent(nconf
);
245 (void) syslog(LOG_ERR
,
246 "svc%s_create: could not open connection", netid
);
252 memset(&sccsin
, 0, sizeof sccsin
);
253 sccsin
.sin_family
= AF_INET
;
254 bindresvport(fd
, &sccsin
);
255 listen(fd
, SOMAXCONN
);
256 svc
= svc_tli_create(fd
, nconf
, NULL
, sendsize
, recvsize
);
257 (void) freenetconfigent(nconf
);
263 port
= (((struct sockaddr_in
*)svc
->xp_ltaddr
.buf
)->sin_port
);
264 svc
->xp_port
= ntohs(port
);
269 svctcp_create(int fd
, u_int sendsize
, u_int recvsize
)
271 return svc_com_create(fd
, sendsize
, recvsize
, "tcp");
275 svcudp_bufcreate(int fd
, u_int sendsz
, u_int recvsz
)
277 return svc_com_create(fd
, sendsz
, recvsz
, "udp");
281 svcfd_create(int fd
, u_int sendsize
, u_int recvsize
)
283 return svc_fd_create(fd
, sendsize
, recvsize
);
288 svcudp_create(int fd
)
290 return svc_com_create(fd
, UDPMSGSIZE
, UDPMSGSIZE
, "udp");
296 return svc_raw_create();
300 get_myaddress(struct sockaddr_in
*addr
)
303 _DIAGASSERT(addr
!= NULL
);
305 memset((void *) addr
, 0, sizeof(*addr
));
306 addr
->sin_family
= AF_INET
;
307 addr
->sin_port
= htons(PMAPPORT
);
308 addr
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
313 * For connectionless "udp" transport. Obsoleted by rpc_call().
316 callrpc(char *host
, int prognum
, int versnum
, int procnum
,
317 xdrproc_t inproc
, char *in
, xdrproc_t outproc
, char *out
)
319 return (int)rpc_call(host
, (rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
320 (rpcproc_t
)procnum
, inproc
, in
, outproc
, out
, "udp");
324 * For connectionless kind of transport. Obsoleted by rpc_reg()
327 registerrpc(int prognum
, int versnum
, int procnum
,
328 char *(*progname
)(char [UDPMSGSIZE
]),
329 xdrproc_t inproc
, xdrproc_t outproc
)
331 return rpc_reg((rpcprog_t
)prognum
, (rpcvers_t
)versnum
,
332 (rpcproc_t
)procnum
, progname
, inproc
, outproc
, __UNCONST("udp"));
336 * All the following clnt_broadcast stuff is convulated; it supports
337 * the earlier calling style of the callback function
340 static thread_key_t clnt_broadcast_key
;
342 static resultproc_t clnt_broadcast_result_main
;
345 * Need to translate the netbuf address into sockaddr_in address.
346 * Dont care about netid here.
351 char *resultp
, /* results of the call */
352 struct netbuf
*addr
, /* address of the guy who responded */
353 struct netconfig
*nconf
) /* Netconf of the transport */
355 resultproc_t clnt_broadcast_result
;
357 _DIAGASSERT(resultp
!= NULL
);
358 _DIAGASSERT(addr
!= NULL
);
359 _DIAGASSERT(nconf
!= NULL
);
361 if (strcmp(nconf
->nc_netid
, "udp"))
364 if (__isthreaded
== 0)
365 clnt_broadcast_result
= clnt_broadcast_result_main
;
367 clnt_broadcast_result
= thr_getspecific(clnt_broadcast_key
);
369 clnt_broadcast_result
= clnt_broadcast_result_main
;
371 return (*clnt_broadcast_result
)(resultp
,
372 (struct sockaddr_in
*)addr
->buf
);
376 static once_t clnt_broadcast_once
= ONCE_INITIALIZER
;
379 clnt_broadcast_setup(void)
382 thr_keycreate(&clnt_broadcast_key
, free
);
387 * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
391 u_long prog
, /* program number */
392 u_long vers
, /* version number */
393 u_long proc
, /* procedure number */
394 xdrproc_t xargs
, /* xdr routine for args */
395 caddr_t argsp
, /* pointer to args */
396 xdrproc_t xresults
, /* xdr routine for results */
397 caddr_t resultsp
, /* pointer to results */
398 resultproc_t eachresult
) /* call with each result obtained */
401 if (__isthreaded
== 0)
402 clnt_broadcast_result_main
= eachresult
;
404 thr_once(&clnt_broadcast_once
, clnt_broadcast_setup
);
405 thr_setspecific(clnt_broadcast_key
, (void *) eachresult
);
408 clnt_broadcast_result_main
= eachresult
;
410 return rpc_broadcast((rpcprog_t
)prog
, (rpcvers_t
)vers
,
411 (rpcproc_t
)proc
, xargs
, argsp
, xresults
, resultsp
,
412 (resultproc_t
) rpc_wrap_bcast
, "udp");