svc_generic.c revision 1.2.4.2 1 1.2.4.2 minoura /* $NetBSD: svc_generic.c,v 1.2.4.2 2000/06/23 16:17:51 minoura Exp $ */
2 1.2.4.2 minoura
3 1.2.4.2 minoura /*
4 1.2.4.2 minoura * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 1.2.4.2 minoura * unrestricted use provided that this legend is included on all tape
6 1.2.4.2 minoura * media and as a part of the software program in whole or part. Users
7 1.2.4.2 minoura * may copy or modify Sun RPC without charge, but are not authorized
8 1.2.4.2 minoura * to license or distribute it to anyone else except as part of a product or
9 1.2.4.2 minoura * program developed by the user.
10 1.2.4.2 minoura *
11 1.2.4.2 minoura * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 1.2.4.2 minoura * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 1.2.4.2 minoura * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 1.2.4.2 minoura *
15 1.2.4.2 minoura * Sun RPC is provided with no support and without any obligation on the
16 1.2.4.2 minoura * part of Sun Microsystems, Inc. to assist in its use, correction,
17 1.2.4.2 minoura * modification or enhancement.
18 1.2.4.2 minoura *
19 1.2.4.2 minoura * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 1.2.4.2 minoura * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 1.2.4.2 minoura * OR ANY PART THEREOF.
22 1.2.4.2 minoura *
23 1.2.4.2 minoura * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 1.2.4.2 minoura * or profits or other special, indirect and consequential damages, even if
25 1.2.4.2 minoura * Sun has been advised of the possibility of such damages.
26 1.2.4.2 minoura *
27 1.2.4.2 minoura * Sun Microsystems, Inc.
28 1.2.4.2 minoura * 2550 Garcia Avenue
29 1.2.4.2 minoura * Mountain View, California 94043
30 1.2.4.2 minoura */
31 1.2.4.2 minoura
32 1.2.4.2 minoura /*
33 1.2.4.2 minoura * Copyright (c) 1986-1991 by Sun Microsystems Inc.
34 1.2.4.2 minoura */
35 1.2.4.2 minoura
36 1.2.4.2 minoura /* #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" */
37 1.2.4.2 minoura
38 1.2.4.2 minoura #if 0
39 1.2.4.2 minoura #if !defined(lint) && defined(SCCSIDS)
40 1.2.4.2 minoura static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
41 1.2.4.2 minoura #endif
42 1.2.4.2 minoura #endif
43 1.2.4.2 minoura
44 1.2.4.2 minoura /*
45 1.2.4.2 minoura * svc_generic.c, Server side for RPC.
46 1.2.4.2 minoura *
47 1.2.4.2 minoura */
48 1.2.4.2 minoura
49 1.2.4.2 minoura #include "namespace.h"
50 1.2.4.2 minoura #include "reentrant.h"
51 1.2.4.2 minoura #include <sys/types.h>
52 1.2.4.2 minoura #include <sys/socket.h>
53 1.2.4.2 minoura #include <netinet/in.h>
54 1.2.4.2 minoura #include <rpc/rpc.h>
55 1.2.4.2 minoura #include <stdio.h>
56 1.2.4.2 minoura #include <errno.h>
57 1.2.4.2 minoura #include <malloc.h>
58 1.2.4.2 minoura #include <string.h>
59 1.2.4.2 minoura #include <unistd.h>
60 1.2.4.2 minoura #include <err.h>
61 1.2.4.2 minoura
62 1.2.4.2 minoura #include "rpc_com.h"
63 1.2.4.2 minoura
64 1.2.4.2 minoura #ifdef __weak_alias
65 1.2.4.2 minoura __weak_alias(svc_create,_svc_create)
66 1.2.4.2 minoura __weak_alias(svc_tp_create,_svc_tp_create)
67 1.2.4.2 minoura __weak_alias(svc_tli_create,_svc_tli_create)
68 1.2.4.2 minoura #endif
69 1.2.4.2 minoura
70 1.2.4.2 minoura extern int __svc_vc_setflag __P((SVCXPRT *, int));
71 1.2.4.2 minoura
72 1.2.4.2 minoura /*
73 1.2.4.2 minoura * The highest level interface for server creation.
74 1.2.4.2 minoura * It tries for all the nettokens in that particular class of token
75 1.2.4.2 minoura * and returns the number of handles it can create and/or find.
76 1.2.4.2 minoura *
77 1.2.4.2 minoura * It creates a link list of all the handles it could create.
78 1.2.4.2 minoura * If svc_create() is called multiple times, it uses the handle
79 1.2.4.2 minoura * created earlier instead of creating a new handle every time.
80 1.2.4.2 minoura */
81 1.2.4.2 minoura int
82 1.2.4.2 minoura svc_create(dispatch, prognum, versnum, nettype)
83 1.2.4.2 minoura void (*dispatch) __P((struct svc_req *, SVCXPRT *));
84 1.2.4.2 minoura rpcprog_t prognum; /* Program number */
85 1.2.4.2 minoura rpcvers_t versnum; /* Version number */
86 1.2.4.2 minoura const char *nettype; /* Networktype token */
87 1.2.4.2 minoura {
88 1.2.4.2 minoura struct xlist {
89 1.2.4.2 minoura SVCXPRT *xprt; /* Server handle */
90 1.2.4.2 minoura struct xlist *next; /* Next item */
91 1.2.4.2 minoura } *l;
92 1.2.4.2 minoura static struct xlist *xprtlist; /* A link list of all the handles */
93 1.2.4.2 minoura int num = 0;
94 1.2.4.2 minoura SVCXPRT *xprt;
95 1.2.4.2 minoura struct netconfig *nconf;
96 1.2.4.2 minoura void *handle;
97 1.2.4.2 minoura #ifdef __REENT
98 1.2.4.2 minoura extern mutex_t xprtlist_lock;
99 1.2.4.2 minoura #endif
100 1.2.4.2 minoura
101 1.2.4.2 minoura /* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
102 1.2.4.2 minoura
103 1.2.4.2 minoura if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
104 1.2.4.2 minoura warnx("svc_create: unknown protocol");
105 1.2.4.2 minoura return (0);
106 1.2.4.2 minoura }
107 1.2.4.2 minoura while ((nconf = __rpc_getconf(handle))) {
108 1.2.4.2 minoura mutex_lock(&xprtlist_lock);
109 1.2.4.2 minoura for (l = xprtlist; l; l = l->next) {
110 1.2.4.2 minoura if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
111 1.2.4.2 minoura /* Found an old one, use it */
112 1.2.4.2 minoura (void) rpcb_unset(prognum, versnum, nconf);
113 1.2.4.2 minoura if (svc_reg(l->xprt, prognum, versnum,
114 1.2.4.2 minoura dispatch, nconf) == FALSE)
115 1.2.4.2 minoura warnx(
116 1.2.4.2 minoura "svc_create: could not register prog %u vers %u on %s",
117 1.2.4.2 minoura (unsigned)prognum, (unsigned)versnum,
118 1.2.4.2 minoura nconf->nc_netid);
119 1.2.4.2 minoura else
120 1.2.4.2 minoura num++;
121 1.2.4.2 minoura break;
122 1.2.4.2 minoura }
123 1.2.4.2 minoura }
124 1.2.4.2 minoura if (l == (struct xlist *)NULL) {
125 1.2.4.2 minoura /* It was not found. Now create a new one */
126 1.2.4.2 minoura xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
127 1.2.4.2 minoura if (xprt) {
128 1.2.4.2 minoura l = (struct xlist *)malloc(sizeof (*l));
129 1.2.4.2 minoura if (l == (struct xlist *)NULL) {
130 1.2.4.2 minoura warnx("svc_create: no memory");
131 1.2.4.2 minoura mutex_unlock(&xprtlist_lock);
132 1.2.4.2 minoura return (0);
133 1.2.4.2 minoura }
134 1.2.4.2 minoura l->xprt = xprt;
135 1.2.4.2 minoura l->next = xprtlist;
136 1.2.4.2 minoura xprtlist = l;
137 1.2.4.2 minoura num++;
138 1.2.4.2 minoura }
139 1.2.4.2 minoura }
140 1.2.4.2 minoura mutex_unlock(&xprtlist_lock);
141 1.2.4.2 minoura }
142 1.2.4.2 minoura __rpc_endconf(handle);
143 1.2.4.2 minoura /*
144 1.2.4.2 minoura * In case of num == 0; the error messages are generated by the
145 1.2.4.2 minoura * underlying layers; and hence not needed here.
146 1.2.4.2 minoura */
147 1.2.4.2 minoura return (num);
148 1.2.4.2 minoura }
149 1.2.4.2 minoura
150 1.2.4.2 minoura /*
151 1.2.4.2 minoura * The high level interface to svc_tli_create().
152 1.2.4.2 minoura * It tries to create a server for "nconf" and registers the service
153 1.2.4.2 minoura * with the rpcbind. It calls svc_tli_create();
154 1.2.4.2 minoura */
155 1.2.4.2 minoura SVCXPRT *
156 1.2.4.2 minoura svc_tp_create(dispatch, prognum, versnum, nconf)
157 1.2.4.2 minoura void (*dispatch) __P((struct svc_req *, SVCXPRT *));
158 1.2.4.2 minoura rpcprog_t prognum; /* Program number */
159 1.2.4.2 minoura rpcvers_t versnum; /* Version number */
160 1.2.4.2 minoura const struct netconfig *nconf; /* Netconfig structure for the network */
161 1.2.4.2 minoura {
162 1.2.4.2 minoura SVCXPRT *xprt;
163 1.2.4.2 minoura
164 1.2.4.2 minoura if (nconf == (struct netconfig *)NULL) {
165 1.2.4.2 minoura warnx(
166 1.2.4.2 minoura "svc_tp_create: invalid netconfig structure for prog %u vers %u",
167 1.2.4.2 minoura (unsigned)prognum, (unsigned)versnum);
168 1.2.4.2 minoura return ((SVCXPRT *)NULL);
169 1.2.4.2 minoura }
170 1.2.4.2 minoura xprt = svc_tli_create(RPC_ANYFD, nconf, (struct t_bind *)NULL, 0, 0);
171 1.2.4.2 minoura if (xprt == (SVCXPRT *)NULL) {
172 1.2.4.2 minoura return ((SVCXPRT *)NULL);
173 1.2.4.2 minoura }
174 1.2.4.2 minoura (void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf);
175 1.2.4.2 minoura if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
176 1.2.4.2 minoura warnx(
177 1.2.4.2 minoura "svc_tp_create: Could not register prog %u vers %u on %s",
178 1.2.4.2 minoura (unsigned)prognum, (unsigned)versnum,
179 1.2.4.2 minoura nconf->nc_netid);
180 1.2.4.2 minoura SVC_DESTROY(xprt);
181 1.2.4.2 minoura return ((SVCXPRT *)NULL);
182 1.2.4.2 minoura }
183 1.2.4.2 minoura return (xprt);
184 1.2.4.2 minoura }
185 1.2.4.2 minoura
186 1.2.4.2 minoura /*
187 1.2.4.2 minoura * If fd is RPC_ANYFD, then it opens a fd for the given transport
188 1.2.4.2 minoura * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
189 1.2.4.2 minoura * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
190 1.2.4.2 minoura * NULL bindadr and Connection oriented transports, the value of qlen
191 1.2.4.2 minoura * is set to 8.
192 1.2.4.2 minoura *
193 1.2.4.2 minoura * If sendsz or recvsz are zero, their default values are chosen.
194 1.2.4.2 minoura */
195 1.2.4.2 minoura SVCXPRT *
196 1.2.4.2 minoura svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
197 1.2.4.2 minoura int fd; /* Connection end point */
198 1.2.4.2 minoura const struct netconfig *nconf; /* Netconfig struct for nettoken */
199 1.2.4.2 minoura const struct t_bind *bindaddr; /* Local bind address */
200 1.2.4.2 minoura u_int sendsz; /* Max sendsize */
201 1.2.4.2 minoura u_int recvsz; /* Max recvsize */
202 1.2.4.2 minoura {
203 1.2.4.2 minoura register SVCXPRT *xprt = NULL; /* service handle */
204 1.2.4.2 minoura bool_t madefd = FALSE; /* whether fd opened here */
205 1.2.4.2 minoura struct __rpc_sockinfo si;
206 1.2.4.2 minoura struct sockaddr_storage ss;
207 1.2.4.2 minoura int active = 0;
208 1.2.4.2 minoura socklen_t slen;
209 1.2.4.2 minoura
210 1.2.4.2 minoura if (fd == RPC_ANYFD) {
211 1.2.4.2 minoura if (nconf == (struct netconfig *)NULL) {
212 1.2.4.2 minoura warnx("svc_tli_create: invalid netconfig");
213 1.2.4.2 minoura return ((SVCXPRT *)NULL);
214 1.2.4.2 minoura }
215 1.2.4.2 minoura fd = __rpc_nconf2fd(nconf);
216 1.2.4.2 minoura if (fd == -1) {
217 1.2.4.2 minoura warnx(
218 1.2.4.2 minoura "svc_tli_create: could not open connection for %s",
219 1.2.4.2 minoura nconf->nc_netid);
220 1.2.4.2 minoura return ((SVCXPRT *)NULL);
221 1.2.4.2 minoura }
222 1.2.4.2 minoura __rpc_nconf2sockinfo(nconf, &si);
223 1.2.4.2 minoura madefd = TRUE;
224 1.2.4.2 minoura } else {
225 1.2.4.2 minoura /*
226 1.2.4.2 minoura * It is an open descriptor. Get the transport info.
227 1.2.4.2 minoura */
228 1.2.4.2 minoura if (!__rpc_fd2sockinfo(fd, &si)) {
229 1.2.4.2 minoura warnx(
230 1.2.4.2 minoura "svc_tli_create: could not get transport information");
231 1.2.4.2 minoura return ((SVCXPRT *)NULL);
232 1.2.4.2 minoura }
233 1.2.4.2 minoura }
234 1.2.4.2 minoura
235 1.2.4.2 minoura /*
236 1.2.4.2 minoura * If the fd is unbound, try to bind it.
237 1.2.4.2 minoura */
238 1.2.4.2 minoura if (madefd || !__rpc_sockisbound(fd)) {
239 1.2.4.2 minoura if (bindaddr == NULL) {
240 1.2.4.2 minoura if (bindresvport(fd, NULL) < 0) {
241 1.2.4.2 minoura memset(&ss, 0, sizeof ss);
242 1.2.4.2 minoura ss.ss_family = si.si_af;
243 1.2.4.2 minoura ss.ss_len = si.si_alen;
244 1.2.4.2 minoura if (bind(fd, (struct sockaddr *)(void *)&ss,
245 1.2.4.2 minoura si.si_alen) < 0) {
246 1.2.4.2 minoura warnx(
247 1.2.4.2 minoura "svc_tli_create: could not bind to anonymous port");
248 1.2.4.2 minoura goto freedata;
249 1.2.4.2 minoura }
250 1.2.4.2 minoura }
251 1.2.4.2 minoura listen(fd, SOMAXCONN);
252 1.2.4.2 minoura } else {
253 1.2.4.2 minoura if (bind(fd, (struct sockaddr *)&bindaddr->addr.buf,
254 1.2.4.2 minoura si.si_alen) < 0) {
255 1.2.4.2 minoura warnx(
256 1.2.4.2 minoura "svc_tli_create: could not bind to requested address");
257 1.2.4.2 minoura goto freedata;
258 1.2.4.2 minoura }
259 1.2.4.2 minoura listen(fd, bindaddr->qlen);
260 1.2.4.2 minoura }
261 1.2.4.2 minoura
262 1.2.4.2 minoura }
263 1.2.4.2 minoura /*
264 1.2.4.2 minoura * call transport specific function.
265 1.2.4.2 minoura */
266 1.2.4.2 minoura switch (si.si_socktype) {
267 1.2.4.2 minoura case SOCK_STREAM:
268 1.2.4.2 minoura slen = sizeof ss;
269 1.2.4.2 minoura if (getpeername(fd, (struct sockaddr *)&ss, &slen)
270 1.2.4.2 minoura == 0) {
271 1.2.4.2 minoura active = 1;
272 1.2.4.2 minoura /* accepted socket */
273 1.2.4.2 minoura xprt = svc_fd_create(fd, sendsz, recvsz);
274 1.2.4.2 minoura } else
275 1.2.4.2 minoura xprt = svc_vc_create(fd, sendsz, recvsz);
276 1.2.4.2 minoura if (!nconf || !xprt)
277 1.2.4.2 minoura break;
278 1.2.4.2 minoura #if 0
279 1.2.4.2 minoura /* XXX fvdl */
280 1.2.4.2 minoura if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
281 1.2.4.2 minoura strcmp(nconf->nc_protofmly, "inet6") == 0)
282 1.2.4.2 minoura (void) __svc_vc_setflag(xprt, TRUE);
283 1.2.4.2 minoura #endif
284 1.2.4.2 minoura break;
285 1.2.4.2 minoura case SOCK_DGRAM:
286 1.2.4.2 minoura xprt = svc_dg_create(fd, sendsz, recvsz);
287 1.2.4.2 minoura break;
288 1.2.4.2 minoura default:
289 1.2.4.2 minoura warnx("svc_tli_create: bad service type");
290 1.2.4.2 minoura goto freedata;
291 1.2.4.2 minoura }
292 1.2.4.2 minoura
293 1.2.4.2 minoura if (xprt == (SVCXPRT *)NULL)
294 1.2.4.2 minoura /*
295 1.2.4.2 minoura * The error messages here are spitted out by the lower layers:
296 1.2.4.2 minoura * svc_vc_create(), svc_fd_create() and svc_dg_create().
297 1.2.4.2 minoura */
298 1.2.4.2 minoura goto freedata;
299 1.2.4.2 minoura
300 1.2.4.2 minoura /* Fill in type of service */
301 1.2.4.2 minoura xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
302 1.2.4.2 minoura
303 1.2.4.2 minoura if (nconf) {
304 1.2.4.2 minoura xprt->xp_netid = strdup(nconf->nc_netid);
305 1.2.4.2 minoura xprt->xp_tp = strdup(nconf->nc_device);
306 1.2.4.2 minoura }
307 1.2.4.2 minoura return (xprt);
308 1.2.4.2 minoura
309 1.2.4.2 minoura freedata:
310 1.2.4.2 minoura if (madefd)
311 1.2.4.2 minoura (void) close(fd);
312 1.2.4.2 minoura if (xprt) {
313 1.2.4.2 minoura if (!madefd) /* so that svc_destroy doesnt close fd */
314 1.2.4.2 minoura xprt->xp_fd = RPC_ANYFD;
315 1.2.4.2 minoura SVC_DESTROY(xprt);
316 1.2.4.2 minoura }
317 1.2.4.2 minoura return ((SVCXPRT *)NULL);
318 1.2.4.2 minoura }
319