1 /* $NetBSD: svc_generic.c,v 1.10 2008/04/25 17:44:44 christos 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
33 * Copyright (c) 1986-1991 by Sun Microsystems Inc.
36 /* #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" */
38 #include <sys/cdefs.h>
39 #if defined(LIBC_SCCS) && !defined(lint)
41 static char sccsid
[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
43 __RCSID("$NetBSD: svc_generic.c,v 1.10 2008/04/25 17:44:44 christos Exp $");
48 * svc_generic.c, Server side for RPC.
52 #include "namespace.h"
53 #include "reentrant.h"
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <netinet/in.h>
58 #include <rpc/nettype.h>
66 #include "rpc_internal.h"
69 __weak_alias(svc_create
,_svc_create
)
70 __weak_alias(svc_tp_create
,_svc_tp_create
)
71 __weak_alias(svc_tli_create
,_svc_tli_create
)
74 extern int __svc_vc_setflag
__P((SVCXPRT
*, int));
77 * The highest level interface for server creation.
78 * It tries for all the nettokens in that particular class of token
79 * and returns the number of handles it can create and/or find.
81 * It creates a link list of all the handles it could create.
82 * If svc_create() is called multiple times, it uses the handle
83 * created earlier instead of creating a new handle every time.
86 svc_create(dispatch
, prognum
, versnum
, nettype
)
87 void (*dispatch
) __P((struct svc_req
*, SVCXPRT
*));
88 rpcprog_t prognum
; /* Program number */
89 rpcvers_t versnum
; /* Version number */
90 const char *nettype
; /* Networktype token */
93 SVCXPRT
*xprt
; /* Server handle */
94 struct xlist
*next
; /* Next item */
96 static struct xlist
*xprtlist
; /* A link list of all the handles */
99 struct netconfig
*nconf
;
102 extern mutex_t xprtlist_lock
;
105 /* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
107 if ((handle
= __rpc_setconf(nettype
)) == NULL
) {
108 warnx("svc_create: unknown protocol");
111 while ((nconf
= __rpc_getconf(handle
)) != NULL
) {
112 mutex_lock(&xprtlist_lock
);
113 for (l
= xprtlist
; l
; l
= l
->next
) {
114 if (strcmp(l
->xprt
->xp_netid
, nconf
->nc_netid
) == 0) {
115 /* Found an old one, use it */
116 (void) rpcb_unset(prognum
, versnum
, nconf
);
117 if (svc_reg(l
->xprt
, prognum
, versnum
,
118 dispatch
, nconf
) == FALSE
)
120 "svc_create: could not register prog %u vers %u on %s",
121 (unsigned)prognum
, (unsigned)versnum
,
129 /* It was not found. Now create a new one */
130 xprt
= svc_tp_create(dispatch
, prognum
, versnum
, nconf
);
132 l
= malloc(sizeof(*l
));
134 warnx("svc_create: no memory");
135 mutex_unlock(&xprtlist_lock
);
144 mutex_unlock(&xprtlist_lock
);
146 __rpc_endconf(handle
);
148 * In case of num == 0; the error messages are generated by the
149 * underlying layers; and hence not needed here.
155 * The high level interface to svc_tli_create().
156 * It tries to create a server for "nconf" and registers the service
157 * with the rpcbind. It calls svc_tli_create();
160 svc_tp_create(dispatch
, prognum
, versnum
, nconf
)
161 void (*dispatch
) __P((struct svc_req
*, SVCXPRT
*));
162 rpcprog_t prognum
; /* Program number */
163 rpcvers_t versnum
; /* Version number */
164 const struct netconfig
*nconf
; /* Netconfig structure for the network */
170 "svc_tp_create: invalid netconfig structure for prog %u vers %u",
171 (unsigned)prognum
, (unsigned)versnum
);
174 xprt
= svc_tli_create(RPC_ANYFD
, nconf
, NULL
, 0, 0);
178 (void) rpcb_unset(prognum
, versnum
, __UNCONST(nconf
));
179 if (svc_reg(xprt
, prognum
, versnum
, dispatch
, nconf
) == FALSE
) {
181 "svc_tp_create: Could not register prog %u vers %u on %s",
182 (unsigned)prognum
, (unsigned)versnum
,
191 * If fd is RPC_ANYFD, then it opens a fd for the given transport
192 * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
193 * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
194 * NULL bindadr and Connection oriented transports, the value of qlen
197 * If sendsz or recvsz are zero, their default values are chosen.
200 svc_tli_create(fd
, nconf
, bindaddr
, sendsz
, recvsz
)
201 int fd
; /* Connection end point */
202 const struct netconfig
*nconf
; /* Netconfig struct for nettoken */
203 const struct t_bind
*bindaddr
; /* Local bind address */
204 u_int sendsz
; /* Max sendsize */
205 u_int recvsz
; /* Max recvsize */
207 SVCXPRT
*xprt
= NULL
; /* service handle */
208 bool_t madefd
= FALSE
; /* whether fd opened here */
209 struct __rpc_sockinfo si
;
210 struct sockaddr_storage ss
;
213 if (fd
== RPC_ANYFD
) {
215 warnx("svc_tli_create: invalid netconfig");
218 fd
= __rpc_nconf2fd(nconf
);
221 "svc_tli_create: could not open connection for %s",
225 __rpc_nconf2sockinfo(nconf
, &si
);
229 * It is an open descriptor. Get the transport info.
231 if (!__rpc_fd2sockinfo(fd
, &si
)) {
233 "svc_tli_create: could not get transport information");
239 * If the fd is unbound, try to bind it.
241 if (madefd
|| !__rpc_sockisbound(fd
)) {
242 if (bindaddr
== NULL
) {
243 if (bindresvport(fd
, NULL
) < 0) {
244 memset(&ss
, 0, sizeof ss
);
245 ss
.ss_family
= si
.si_af
;
246 ss
.ss_len
= si
.si_alen
;
247 if (bind(fd
, (struct sockaddr
*)(void *)&ss
,
248 (socklen_t
)si
.si_alen
) < 0) {
250 "svc_tli_create: could not bind to anonymous port");
254 listen(fd
, SOMAXCONN
);
257 (struct sockaddr
*)bindaddr
->addr
.buf
,
258 (socklen_t
)si
.si_alen
) < 0) {
260 "svc_tli_create: could not bind to requested address");
263 listen(fd
, (int)bindaddr
->qlen
);
268 * call transport specific function.
270 switch (si
.si_socktype
) {
273 if (getpeername(fd
, (struct sockaddr
*)(void *)&ss
, &slen
)
275 /* accepted socket */
276 xprt
= svc_fd_create(fd
, sendsz
, recvsz
);
278 xprt
= svc_vc_create(fd
, sendsz
, recvsz
);
283 if (strcmp(nconf
->nc_protofmly
, "inet") == 0 ||
284 strcmp(nconf
->nc_protofmly
, "inet6") == 0)
285 (void) __svc_vc_setflag(xprt
, TRUE
);
289 xprt
= svc_dg_create(fd
, sendsz
, recvsz
);
292 warnx("svc_tli_create: bad service type");
298 * The error messages here are spitted out by the lower layers:
299 * svc_vc_create(), svc_fd_create() and svc_dg_create().
303 /* Fill in type of service */
304 xprt
->xp_type
= __rpc_socktype2seman(si
.si_socktype
);
307 xprt
->xp_netid
= strdup(nconf
->nc_netid
);
308 xprt
->xp_tp
= strdup(nconf
->nc_device
);
309 if (xprt
->xp_netid
== NULL
|| xprt
->xp_tp
== NULL
) {