rpcb_clnt.c revision 1.3.4.2 1 1.3.4.2 minoura /* $NetBSD: rpcb_clnt.c,v 1.3.4.2 2000/06/23 16:17:49 minoura Exp $ */
2 1.3.4.2 minoura
3 1.3.4.2 minoura /*
4 1.3.4.2 minoura * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 1.3.4.2 minoura * unrestricted use provided that this legend is included on all tape
6 1.3.4.2 minoura * media and as a part of the software program in whole or part. Users
7 1.3.4.2 minoura * may copy or modify Sun RPC without charge, but are not authorized
8 1.3.4.2 minoura * to license or distribute it to anyone else except as part of a product or
9 1.3.4.2 minoura * program developed by the user.
10 1.3.4.2 minoura *
11 1.3.4.2 minoura * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 1.3.4.2 minoura * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 1.3.4.2 minoura * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14 1.3.4.2 minoura *
15 1.3.4.2 minoura * Sun RPC is provided with no support and without any obligation on the
16 1.3.4.2 minoura * part of Sun Microsystems, Inc. to assist in its use, correction,
17 1.3.4.2 minoura * modification or enhancement.
18 1.3.4.2 minoura *
19 1.3.4.2 minoura * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 1.3.4.2 minoura * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 1.3.4.2 minoura * OR ANY PART THEREOF.
22 1.3.4.2 minoura *
23 1.3.4.2 minoura * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 1.3.4.2 minoura * or profits or other special, indirect and consequential damages, even if
25 1.3.4.2 minoura * Sun has been advised of the possibility of such damages.
26 1.3.4.2 minoura *
27 1.3.4.2 minoura * Sun Microsystems, Inc.
28 1.3.4.2 minoura * 2550 Garcia Avenue
29 1.3.4.2 minoura * Mountain View, California 94043
30 1.3.4.2 minoura */
31 1.3.4.2 minoura /*
32 1.3.4.2 minoura * Copyright (c) 1986-1991 by Sun Microsystems Inc.
33 1.3.4.2 minoura */
34 1.3.4.2 minoura
35 1.3.4.2 minoura /* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */
36 1.3.4.2 minoura
37 1.3.4.2 minoura
38 1.3.4.2 minoura #if 0
39 1.3.4.2 minoura #if !defined(lint) && defined(SCCSIDS)
40 1.3.4.2 minoura static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro";
41 1.3.4.2 minoura #endif
42 1.3.4.2 minoura #endif
43 1.3.4.2 minoura
44 1.3.4.2 minoura /*
45 1.3.4.2 minoura * rpcb_clnt.c
46 1.3.4.2 minoura * interface to rpcbind rpc service.
47 1.3.4.2 minoura *
48 1.3.4.2 minoura * Copyright (C) 1988, Sun Microsystems, Inc.
49 1.3.4.2 minoura */
50 1.3.4.2 minoura
51 1.3.4.2 minoura #include "namespace.h"
52 1.3.4.2 minoura #include "reentrant.h"
53 1.3.4.2 minoura #include <sys/types.h>
54 1.3.4.2 minoura #include <sys/socket.h>
55 1.3.4.2 minoura #include <sys/un.h>
56 1.3.4.2 minoura #include <sys/utsname.h>
57 1.3.4.2 minoura #include <rpc/rpc.h>
58 1.3.4.2 minoura #include <rpc/rpcb_prot.h>
59 1.3.4.2 minoura #include <netconfig.h>
60 1.3.4.2 minoura #ifdef PORTMAP
61 1.3.4.2 minoura #include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
62 1.3.4.2 minoura #include <rpc/pmap_prot.h>
63 1.3.4.2 minoura #endif
64 1.3.4.2 minoura #include <stdio.h>
65 1.3.4.2 minoura #include <errno.h>
66 1.3.4.2 minoura #include <stdlib.h>
67 1.3.4.2 minoura #include <string.h>
68 1.3.4.2 minoura #include <unistd.h>
69 1.3.4.2 minoura #include <netdb.h>
70 1.3.4.2 minoura #include <syslog.h>
71 1.3.4.2 minoura
72 1.3.4.2 minoura #include "rpc_com.h"
73 1.3.4.2 minoura
74 1.3.4.2 minoura #ifdef __weak_alias
75 1.3.4.2 minoura __weak_alias(rpcb_set,_rpcb_set)
76 1.3.4.2 minoura __weak_alias(rpcb_unset,_rpcb_unset)
77 1.3.4.2 minoura __weak_alias(rpcb_getmaps,_rpcb_getmaps)
78 1.3.4.2 minoura __weak_alias(rpcb_rmtcall,_rpcb_rmtcall)
79 1.3.4.2 minoura __weak_alias(rpcb_gettime,_rpcb_gettime)
80 1.3.4.2 minoura __weak_alias(rpcb_taddr2uaddr,_rpcb_taddr2uaddr)
81 1.3.4.2 minoura __weak_alias(rpcb_uaddr2taddr,_rpcb_uaddr2taddr)
82 1.3.4.2 minoura #endif
83 1.3.4.2 minoura
84 1.3.4.2 minoura static struct timeval tottimeout = { 60, 0 };
85 1.3.4.2 minoura static const struct timeval rmttimeout = { 3, 0 };
86 1.3.4.2 minoura
87 1.3.4.2 minoura extern bool_t xdr_wrapstring __P((XDR *, char **));
88 1.3.4.2 minoura
89 1.3.4.2 minoura static const char nullstring[] = "\000";
90 1.3.4.2 minoura
91 1.3.4.2 minoura #define CACHESIZE 6
92 1.3.4.2 minoura
93 1.3.4.2 minoura struct address_cache {
94 1.3.4.2 minoura char *ac_host;
95 1.3.4.2 minoura char *ac_netid;
96 1.3.4.2 minoura char *ac_uaddr;
97 1.3.4.2 minoura struct netbuf *ac_taddr;
98 1.3.4.2 minoura struct address_cache *ac_next;
99 1.3.4.2 minoura };
100 1.3.4.2 minoura
101 1.3.4.2 minoura static struct address_cache *front;
102 1.3.4.2 minoura static int cachesize;
103 1.3.4.2 minoura
104 1.3.4.2 minoura #define CLCR_GET_RPCB_TIMEOUT 1
105 1.3.4.2 minoura #define CLCR_SET_RPCB_TIMEOUT 2
106 1.3.4.2 minoura
107 1.3.4.2 minoura
108 1.3.4.2 minoura extern int __rpc_lowvers;
109 1.3.4.2 minoura
110 1.3.4.2 minoura static struct address_cache *check_cache __P((const char *, const char *));
111 1.3.4.2 minoura static void delete_cache __P((struct netbuf *));
112 1.3.4.2 minoura static void add_cache __P((const char *, const char *, struct netbuf *,
113 1.3.4.2 minoura char *));
114 1.3.4.2 minoura static CLIENT *getclnthandle __P((const char *, const struct netconfig *,
115 1.3.4.2 minoura char **));
116 1.3.4.2 minoura static CLIENT *local_rpcb __P((void));
117 1.3.4.2 minoura static struct netbuf *got_entry __P((rpcb_entry_list_ptr,
118 1.3.4.2 minoura const struct netconfig *));
119 1.3.4.2 minoura
120 1.3.4.2 minoura /*
121 1.3.4.2 minoura * This routine adjusts the timeout used for calls to the remote rpcbind.
122 1.3.4.2 minoura * Also, this routine can be used to set the use of portmapper version 2
123 1.3.4.2 minoura * only when doing rpc_broadcasts
124 1.3.4.2 minoura * These are private routines that may not be provided in future releases.
125 1.3.4.2 minoura */
126 1.3.4.2 minoura bool_t
127 1.3.4.2 minoura __rpc_control(request, info)
128 1.3.4.2 minoura int request;
129 1.3.4.2 minoura void *info;
130 1.3.4.2 minoura {
131 1.3.4.2 minoura switch (request) {
132 1.3.4.2 minoura case CLCR_GET_RPCB_TIMEOUT:
133 1.3.4.2 minoura *(struct timeval *)info = tottimeout;
134 1.3.4.2 minoura break;
135 1.3.4.2 minoura case CLCR_SET_RPCB_TIMEOUT:
136 1.3.4.2 minoura tottimeout = *(struct timeval *)info;
137 1.3.4.2 minoura break;
138 1.3.4.2 minoura case CLCR_SET_LOWVERS:
139 1.3.4.2 minoura __rpc_lowvers = *(int *)info;
140 1.3.4.2 minoura break;
141 1.3.4.2 minoura case CLCR_GET_LOWVERS:
142 1.3.4.2 minoura *(int *)info = __rpc_lowvers;
143 1.3.4.2 minoura break;
144 1.3.4.2 minoura default:
145 1.3.4.2 minoura return (FALSE);
146 1.3.4.2 minoura }
147 1.3.4.2 minoura return (TRUE);
148 1.3.4.2 minoura }
149 1.3.4.2 minoura
150 1.3.4.2 minoura /*
151 1.3.4.2 minoura * It might seem that a reader/writer lock would be more reasonable here.
152 1.3.4.2 minoura * However because getclnthandle(), the only user of the cache functions,
153 1.3.4.2 minoura * may do a delete_cache() operation if a check_cache() fails to return an
154 1.3.4.2 minoura * address useful to clnt_tli_create(), we may as well use a mutex.
155 1.3.4.2 minoura */
156 1.3.4.2 minoura /*
157 1.3.4.2 minoura * As it turns out, if the cache lock is *not* a reader/writer lock, we will
158 1.3.4.2 minoura * block all clnt_create's if we are trying to connect to a host that's down,
159 1.3.4.2 minoura * since the lock will be held all during that time.
160 1.3.4.2 minoura */
161 1.3.4.2 minoura #ifdef __REENT
162 1.3.4.2 minoura extern rwlock_t rpcbaddr_cache_lock;
163 1.3.4.2 minoura #endif
164 1.3.4.2 minoura
165 1.3.4.2 minoura /*
166 1.3.4.2 minoura * The routines check_cache(), add_cache(), delete_cache() manage the
167 1.3.4.2 minoura * cache of rpcbind addresses for (host, netid).
168 1.3.4.2 minoura */
169 1.3.4.2 minoura
170 1.3.4.2 minoura static struct address_cache *
171 1.3.4.2 minoura check_cache(host, netid)
172 1.3.4.2 minoura const char *host, *netid;
173 1.3.4.2 minoura {
174 1.3.4.2 minoura struct address_cache *cptr;
175 1.3.4.2 minoura
176 1.3.4.2 minoura /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
177 1.3.4.2 minoura
178 1.3.4.2 minoura for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
179 1.3.4.2 minoura if (!strcmp(cptr->ac_host, host) &&
180 1.3.4.2 minoura !strcmp(cptr->ac_netid, netid)) {
181 1.3.4.2 minoura #ifdef ND_DEBUG
182 1.3.4.2 minoura fprintf(stderr, "Found cache entry for %s: %s\n",
183 1.3.4.2 minoura host, netid);
184 1.3.4.2 minoura #endif
185 1.3.4.2 minoura return (cptr);
186 1.3.4.2 minoura }
187 1.3.4.2 minoura }
188 1.3.4.2 minoura return ((struct address_cache *) NULL);
189 1.3.4.2 minoura }
190 1.3.4.2 minoura
191 1.3.4.2 minoura static void
192 1.3.4.2 minoura delete_cache(addr)
193 1.3.4.2 minoura struct netbuf *addr;
194 1.3.4.2 minoura {
195 1.3.4.2 minoura struct address_cache *cptr, *prevptr = NULL;
196 1.3.4.2 minoura
197 1.3.4.2 minoura /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
198 1.3.4.2 minoura for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
199 1.3.4.2 minoura if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
200 1.3.4.2 minoura free(cptr->ac_host);
201 1.3.4.2 minoura free(cptr->ac_netid);
202 1.3.4.2 minoura free(cptr->ac_taddr->buf);
203 1.3.4.2 minoura free(cptr->ac_taddr);
204 1.3.4.2 minoura if (cptr->ac_uaddr)
205 1.3.4.2 minoura free(cptr->ac_uaddr);
206 1.3.4.2 minoura if (prevptr)
207 1.3.4.2 minoura prevptr->ac_next = cptr->ac_next;
208 1.3.4.2 minoura else
209 1.3.4.2 minoura front = cptr->ac_next;
210 1.3.4.2 minoura free(cptr);
211 1.3.4.2 minoura cachesize--;
212 1.3.4.2 minoura break;
213 1.3.4.2 minoura }
214 1.3.4.2 minoura prevptr = cptr;
215 1.3.4.2 minoura }
216 1.3.4.2 minoura }
217 1.3.4.2 minoura
218 1.3.4.2 minoura static void
219 1.3.4.2 minoura add_cache(host, netid, taddr, uaddr)
220 1.3.4.2 minoura const char *host, *netid;
221 1.3.4.2 minoura char *uaddr;
222 1.3.4.2 minoura struct netbuf *taddr;
223 1.3.4.2 minoura {
224 1.3.4.2 minoura struct address_cache *ad_cache, *cptr, *prevptr;
225 1.3.4.2 minoura
226 1.3.4.2 minoura ad_cache = (struct address_cache *)
227 1.3.4.2 minoura malloc(sizeof (struct address_cache));
228 1.3.4.2 minoura if (!ad_cache) {
229 1.3.4.2 minoura return;
230 1.3.4.2 minoura }
231 1.3.4.2 minoura ad_cache->ac_host = strdup(host);
232 1.3.4.2 minoura ad_cache->ac_netid = strdup(netid);
233 1.3.4.2 minoura ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
234 1.3.4.2 minoura ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
235 1.3.4.2 minoura if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
236 1.3.4.2 minoura (uaddr && !ad_cache->ac_uaddr)) {
237 1.3.4.2 minoura return;
238 1.3.4.2 minoura }
239 1.3.4.2 minoura ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
240 1.3.4.2 minoura ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
241 1.3.4.2 minoura if (ad_cache->ac_taddr->buf == NULL) {
242 1.3.4.2 minoura return;
243 1.3.4.2 minoura }
244 1.3.4.2 minoura memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
245 1.3.4.2 minoura #ifdef ND_DEBUG
246 1.3.4.2 minoura fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
247 1.3.4.2 minoura #endif
248 1.3.4.2 minoura
249 1.3.4.2 minoura /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
250 1.3.4.2 minoura
251 1.3.4.2 minoura rwlock_wrlock(&rpcbaddr_cache_lock);
252 1.3.4.2 minoura if (cachesize < CACHESIZE) {
253 1.3.4.2 minoura ad_cache->ac_next = front;
254 1.3.4.2 minoura front = ad_cache;
255 1.3.4.2 minoura cachesize++;
256 1.3.4.2 minoura } else {
257 1.3.4.2 minoura /* Free the last entry */
258 1.3.4.2 minoura cptr = front;
259 1.3.4.2 minoura prevptr = NULL;
260 1.3.4.2 minoura while (cptr->ac_next) {
261 1.3.4.2 minoura prevptr = cptr;
262 1.3.4.2 minoura cptr = cptr->ac_next;
263 1.3.4.2 minoura }
264 1.3.4.2 minoura
265 1.3.4.2 minoura #ifdef ND_DEBUG
266 1.3.4.2 minoura fprintf(stderr, "Deleted from cache: %s : %s\n",
267 1.3.4.2 minoura cptr->ac_host, cptr->ac_netid);
268 1.3.4.2 minoura #endif
269 1.3.4.2 minoura free(cptr->ac_host);
270 1.3.4.2 minoura free(cptr->ac_netid);
271 1.3.4.2 minoura free(cptr->ac_taddr->buf);
272 1.3.4.2 minoura free(cptr->ac_taddr);
273 1.3.4.2 minoura if (cptr->ac_uaddr)
274 1.3.4.2 minoura free(cptr->ac_uaddr);
275 1.3.4.2 minoura
276 1.3.4.2 minoura if (prevptr) {
277 1.3.4.2 minoura prevptr->ac_next = NULL;
278 1.3.4.2 minoura ad_cache->ac_next = front;
279 1.3.4.2 minoura front = ad_cache;
280 1.3.4.2 minoura } else {
281 1.3.4.2 minoura front = ad_cache;
282 1.3.4.2 minoura ad_cache->ac_next = NULL;
283 1.3.4.2 minoura }
284 1.3.4.2 minoura free(cptr);
285 1.3.4.2 minoura }
286 1.3.4.2 minoura rwlock_unlock(&rpcbaddr_cache_lock);
287 1.3.4.2 minoura }
288 1.3.4.2 minoura
289 1.3.4.2 minoura /*
290 1.3.4.2 minoura * This routine will return a client handle that is connected to the
291 1.3.4.2 minoura * rpcbind. Returns NULL on error and free's everything.
292 1.3.4.2 minoura */
293 1.3.4.2 minoura static CLIENT *
294 1.3.4.2 minoura getclnthandle(host, nconf, targaddr)
295 1.3.4.2 minoura const char *host;
296 1.3.4.2 minoura const struct netconfig *nconf;
297 1.3.4.2 minoura char **targaddr;
298 1.3.4.2 minoura {
299 1.3.4.2 minoura register CLIENT *client;
300 1.3.4.2 minoura struct netbuf *addr, taddr;
301 1.3.4.2 minoura struct netbuf addr_to_delete;
302 1.3.4.2 minoura struct __rpc_sockinfo si;
303 1.3.4.2 minoura struct addrinfo hints, *res, *tres;
304 1.3.4.2 minoura struct address_cache *ad_cache;
305 1.3.4.2 minoura char *tmpaddr;
306 1.3.4.2 minoura
307 1.3.4.2 minoura /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
308 1.3.4.2 minoura
309 1.3.4.2 minoura /* Get the address of the rpcbind. Check cache first */
310 1.3.4.2 minoura addr_to_delete.len = 0;
311 1.3.4.2 minoura rwlock_rdlock(&rpcbaddr_cache_lock);
312 1.3.4.2 minoura ad_cache = check_cache(host, nconf->nc_netid);
313 1.3.4.2 minoura if (ad_cache != NULL) {
314 1.3.4.2 minoura addr = ad_cache->ac_taddr;
315 1.3.4.2 minoura client = clnt_tli_create(RPC_ANYFD, nconf, addr, RPCBPROG,
316 1.3.4.2 minoura RPCBVERS4, 0, 0);
317 1.3.4.2 minoura if (client != NULL) {
318 1.3.4.2 minoura if (targaddr)
319 1.3.4.2 minoura *targaddr = ad_cache->ac_uaddr;
320 1.3.4.2 minoura rwlock_unlock(&rpcbaddr_cache_lock);
321 1.3.4.2 minoura return (client);
322 1.3.4.2 minoura }
323 1.3.4.2 minoura addr_to_delete.len = addr->len;
324 1.3.4.2 minoura addr_to_delete.buf = (char *)malloc(addr->len);
325 1.3.4.2 minoura if (addr_to_delete.buf == NULL) {
326 1.3.4.2 minoura addr_to_delete.len = 0;
327 1.3.4.2 minoura } else {
328 1.3.4.2 minoura memcpy(addr_to_delete.buf, addr->buf, addr->len);
329 1.3.4.2 minoura }
330 1.3.4.2 minoura }
331 1.3.4.2 minoura rwlock_unlock(&rpcbaddr_cache_lock);
332 1.3.4.2 minoura if (addr_to_delete.len != 0) {
333 1.3.4.2 minoura /*
334 1.3.4.2 minoura * Assume this may be due to cache data being
335 1.3.4.2 minoura * outdated
336 1.3.4.2 minoura */
337 1.3.4.2 minoura rwlock_wrlock(&rpcbaddr_cache_lock);
338 1.3.4.2 minoura delete_cache(&addr_to_delete);
339 1.3.4.2 minoura rwlock_unlock(&rpcbaddr_cache_lock);
340 1.3.4.2 minoura free(addr_to_delete.buf);
341 1.3.4.2 minoura }
342 1.3.4.2 minoura if (!__rpc_nconf2sockinfo(nconf, &si)) {
343 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
344 1.3.4.2 minoura return NULL;
345 1.3.4.2 minoura }
346 1.3.4.2 minoura
347 1.3.4.2 minoura memset(&hints, 0, sizeof hints);
348 1.3.4.2 minoura hints.ai_family = si.si_af;
349 1.3.4.2 minoura hints.ai_socktype = si.si_socktype;
350 1.3.4.2 minoura hints.ai_protocol = si.si_proto;
351 1.3.4.2 minoura
352 1.3.4.2 minoura #ifdef CLNT_DEBUG
353 1.3.4.2 minoura printf("trying netid %s family %d proto %d socktype %d\n",
354 1.3.4.2 minoura nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
355 1.3.4.2 minoura #endif
356 1.3.4.2 minoura
357 1.3.4.2 minoura if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
358 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
359 1.3.4.2 minoura return NULL;
360 1.3.4.2 minoura }
361 1.3.4.2 minoura
362 1.3.4.2 minoura for (tres = res; tres != NULL; tres = tres->ai_next) {
363 1.3.4.2 minoura taddr.buf = tres->ai_addr;
364 1.3.4.2 minoura taddr.len = taddr.maxlen = tres->ai_addrlen;
365 1.3.4.2 minoura
366 1.3.4.2 minoura #ifdef ND_DEBUG
367 1.3.4.2 minoura {
368 1.3.4.2 minoura char *ua;
369 1.3.4.2 minoura
370 1.3.4.2 minoura ua = taddr2uaddr(nconf, &taddr);
371 1.3.4.2 minoura fprintf(stderr, "Got it [%s]\n", ua);
372 1.3.4.2 minoura free(ua);
373 1.3.4.2 minoura }
374 1.3.4.2 minoura #endif
375 1.3.4.2 minoura
376 1.3.4.2 minoura #ifdef ND_DEBUG
377 1.3.4.2 minoura {
378 1.3.4.2 minoura int i;
379 1.3.4.2 minoura
380 1.3.4.2 minoura fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
381 1.3.4.2 minoura taddr.len, taddr.maxlen);
382 1.3.4.2 minoura fprintf(stderr, "\tAddress is ");
383 1.3.4.2 minoura for (i = 0; i < taddr.len; i++)
384 1.3.4.2 minoura fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
385 1.3.4.2 minoura fprintf(stderr, "\n");
386 1.3.4.2 minoura }
387 1.3.4.2 minoura #endif
388 1.3.4.2 minoura client = clnt_tli_create(RPC_ANYFD, nconf, &taddr, RPCBPROG,
389 1.3.4.2 minoura RPCBVERS4, 0, 0);
390 1.3.4.2 minoura #ifdef ND_DEBUG
391 1.3.4.2 minoura if (! client) {
392 1.3.4.2 minoura clnt_pcreateerror("rpcbind clnt interface");
393 1.3.4.2 minoura }
394 1.3.4.2 minoura #endif
395 1.3.4.2 minoura
396 1.3.4.2 minoura if (client) {
397 1.3.4.2 minoura tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
398 1.3.4.2 minoura add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
399 1.3.4.2 minoura if (targaddr)
400 1.3.4.2 minoura *targaddr = tmpaddr;
401 1.3.4.2 minoura break;
402 1.3.4.2 minoura }
403 1.3.4.2 minoura }
404 1.3.4.2 minoura freeaddrinfo(res);
405 1.3.4.2 minoura return (client);
406 1.3.4.2 minoura }
407 1.3.4.2 minoura
408 1.3.4.2 minoura /* XXX */
409 1.3.4.2 minoura #define IN4_LOCALHOST_STRING "127.0.0.1"
410 1.3.4.2 minoura #define IN6_LOCALHOST_STRING "::1"
411 1.3.4.2 minoura
412 1.3.4.2 minoura /*
413 1.3.4.2 minoura * This routine will return a client handle that is connected to the local
414 1.3.4.2 minoura * rpcbind. Returns NULL on error and free's everything.
415 1.3.4.2 minoura */
416 1.3.4.2 minoura static CLIENT *
417 1.3.4.2 minoura local_rpcb()
418 1.3.4.2 minoura {
419 1.3.4.2 minoura CLIENT *client;
420 1.3.4.2 minoura static struct netconfig *loopnconf;
421 1.3.4.2 minoura static char *hostname;
422 1.3.4.2 minoura #ifdef __REENT
423 1.3.4.2 minoura extern mutex_t loopnconf_lock;
424 1.3.4.2 minoura #endif
425 1.3.4.2 minoura int sock, tsize;
426 1.3.4.2 minoura struct netbuf nbuf;
427 1.3.4.2 minoura struct sockaddr_un sun;
428 1.3.4.2 minoura
429 1.3.4.2 minoura /*
430 1.3.4.2 minoura * Try connecting to the local rpcbind through a local socket
431 1.3.4.2 minoura * first. If this doesn't work, try all transports defined in
432 1.3.4.2 minoura * the netconfig file.
433 1.3.4.2 minoura */
434 1.3.4.2 minoura memset(&sun, 0, sizeof sun);
435 1.3.4.2 minoura sock = socket(AF_LOCAL, SOCK_STREAM, 0);
436 1.3.4.2 minoura if (sock < 0)
437 1.3.4.2 minoura goto try_nconf;
438 1.3.4.2 minoura sun.sun_family = AF_LOCAL;
439 1.3.4.2 minoura strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
440 1.3.4.2 minoura nbuf.len = sun.sun_len = SUN_LEN(&sun);
441 1.3.4.2 minoura nbuf.maxlen = sizeof (struct sockaddr_un);
442 1.3.4.2 minoura nbuf.buf = &sun;
443 1.3.4.2 minoura
444 1.3.4.2 minoura tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
445 1.3.4.2 minoura client = clnt_vc_create(sock, &nbuf, RPCBPROG, RPCBVERS, tsize, tsize);
446 1.3.4.2 minoura
447 1.3.4.2 minoura if (client != NULL)
448 1.3.4.2 minoura return client;
449 1.3.4.2 minoura
450 1.3.4.2 minoura try_nconf:
451 1.3.4.2 minoura
452 1.3.4.2 minoura /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
453 1.3.4.2 minoura mutex_lock(&loopnconf_lock);
454 1.3.4.2 minoura if (loopnconf == NULL) {
455 1.3.4.2 minoura struct netconfig *nconf, *tmpnconf = NULL;
456 1.3.4.2 minoura void *nc_handle;
457 1.3.4.2 minoura int fd;
458 1.3.4.2 minoura
459 1.3.4.2 minoura nc_handle = setnetconfig();
460 1.3.4.2 minoura if (nc_handle == NULL) {
461 1.3.4.2 minoura /* fails to open netconfig file */
462 1.3.4.2 minoura syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
463 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
464 1.3.4.2 minoura mutex_unlock(&loopnconf_lock);
465 1.3.4.2 minoura return (NULL);
466 1.3.4.2 minoura }
467 1.3.4.2 minoura while ((nconf = getnetconfig(nc_handle))) {
468 1.3.4.2 minoura #ifdef INET6
469 1.3.4.2 minoura if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
470 1.3.4.2 minoura #else
471 1.3.4.2 minoura if (
472 1.3.4.2 minoura #endif
473 1.3.4.2 minoura strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
474 1.3.4.2 minoura (nconf->nc_semantics == NC_TPI_COTS ||
475 1.3.4.2 minoura nconf->nc_semantics == NC_TPI_COTS_ORD)) {
476 1.3.4.2 minoura fd = __rpc_nconf2fd(nconf);
477 1.3.4.2 minoura /*
478 1.3.4.2 minoura * Can't create a socket, assume that
479 1.3.4.2 minoura * this family isn't configured in the kernel.
480 1.3.4.2 minoura */
481 1.3.4.2 minoura if (fd < 0)
482 1.3.4.2 minoura continue;
483 1.3.4.2 minoura close(fd);
484 1.3.4.2 minoura tmpnconf = nconf;
485 1.3.4.2 minoura if (!strcmp(nconf->nc_protofmly, NC_INET))
486 1.3.4.2 minoura hostname = IN4_LOCALHOST_STRING;
487 1.3.4.2 minoura else
488 1.3.4.2 minoura hostname = IN6_LOCALHOST_STRING;
489 1.3.4.2 minoura }
490 1.3.4.2 minoura }
491 1.3.4.2 minoura if (tmpnconf == NULL) {
492 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
493 1.3.4.2 minoura mutex_unlock(&loopnconf_lock);
494 1.3.4.2 minoura return (NULL);
495 1.3.4.2 minoura }
496 1.3.4.2 minoura loopnconf = getnetconfigent(tmpnconf->nc_netid);
497 1.3.4.2 minoura /* loopnconf is never freed */
498 1.3.4.2 minoura endnetconfig(nc_handle);
499 1.3.4.2 minoura }
500 1.3.4.2 minoura mutex_unlock(&loopnconf_lock);
501 1.3.4.2 minoura client = getclnthandle(hostname, loopnconf, (char **)NULL);
502 1.3.4.2 minoura return (client);
503 1.3.4.2 minoura }
504 1.3.4.2 minoura
505 1.3.4.2 minoura /*
506 1.3.4.2 minoura * Set a mapping between program, version and address.
507 1.3.4.2 minoura * Calls the rpcbind service to do the mapping.
508 1.3.4.2 minoura */
509 1.3.4.2 minoura bool_t
510 1.3.4.2 minoura rpcb_set(program, version, nconf, address)
511 1.3.4.2 minoura rpcprog_t program;
512 1.3.4.2 minoura rpcvers_t version;
513 1.3.4.2 minoura const struct netconfig *nconf; /* Network structure of transport */
514 1.3.4.2 minoura const struct netbuf *address; /* Services netconfig address */
515 1.3.4.2 minoura {
516 1.3.4.2 minoura register CLIENT *client;
517 1.3.4.2 minoura bool_t rslt = FALSE;
518 1.3.4.2 minoura RPCB parms;
519 1.3.4.2 minoura char uidbuf[32];
520 1.3.4.2 minoura
521 1.3.4.2 minoura /* parameter checking */
522 1.3.4.2 minoura if (nconf == (struct netconfig *)NULL) {
523 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
524 1.3.4.2 minoura return (FALSE);
525 1.3.4.2 minoura }
526 1.3.4.2 minoura if (address == NULL) {
527 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
528 1.3.4.2 minoura return (FALSE);
529 1.3.4.2 minoura }
530 1.3.4.2 minoura client = local_rpcb();
531 1.3.4.2 minoura if (! client) {
532 1.3.4.2 minoura return (FALSE);
533 1.3.4.2 minoura }
534 1.3.4.2 minoura
535 1.3.4.2 minoura /* convert to universal */
536 1.3.4.2 minoura parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
537 1.3.4.2 minoura (struct netbuf *)address);
538 1.3.4.2 minoura if (!parms.r_addr) {
539 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
540 1.3.4.2 minoura return (FALSE); /* no universal address */
541 1.3.4.2 minoura }
542 1.3.4.2 minoura parms.r_prog = program;
543 1.3.4.2 minoura parms.r_vers = version;
544 1.3.4.2 minoura parms.r_netid = nconf->nc_netid;
545 1.3.4.2 minoura /*
546 1.3.4.2 minoura * Though uid is not being used directly, we still send it for
547 1.3.4.2 minoura * completeness. For non-unix platforms, perhaps some other
548 1.3.4.2 minoura * string or an empty string can be sent.
549 1.3.4.2 minoura */
550 1.3.4.2 minoura (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
551 1.3.4.2 minoura parms.r_owner = uidbuf;
552 1.3.4.2 minoura
553 1.3.4.2 minoura CLNT_CALL(client, RPCBPROC_SET, (xdrproc_t) xdr_rpcb, (char *)&parms,
554 1.3.4.2 minoura (xdrproc_t) xdr_bool, (char *)&rslt, tottimeout);
555 1.3.4.2 minoura
556 1.3.4.2 minoura CLNT_DESTROY(client);
557 1.3.4.2 minoura free(parms.r_addr);
558 1.3.4.2 minoura return (rslt);
559 1.3.4.2 minoura }
560 1.3.4.2 minoura
561 1.3.4.2 minoura /*
562 1.3.4.2 minoura * Remove the mapping between program, version and netbuf address.
563 1.3.4.2 minoura * Calls the rpcbind service to do the un-mapping.
564 1.3.4.2 minoura * If netbuf is NULL, unset for all the transports, otherwise unset
565 1.3.4.2 minoura * only for the given transport.
566 1.3.4.2 minoura */
567 1.3.4.2 minoura bool_t
568 1.3.4.2 minoura rpcb_unset(program, version, nconf)
569 1.3.4.2 minoura rpcprog_t program;
570 1.3.4.2 minoura rpcvers_t version;
571 1.3.4.2 minoura const struct netconfig *nconf;
572 1.3.4.2 minoura {
573 1.3.4.2 minoura register CLIENT *client;
574 1.3.4.2 minoura bool_t rslt = FALSE;
575 1.3.4.2 minoura RPCB parms;
576 1.3.4.2 minoura char uidbuf[32];
577 1.3.4.2 minoura
578 1.3.4.2 minoura client = local_rpcb();
579 1.3.4.2 minoura if (! client) {
580 1.3.4.2 minoura return (FALSE);
581 1.3.4.2 minoura }
582 1.3.4.2 minoura
583 1.3.4.2 minoura parms.r_prog = program;
584 1.3.4.2 minoura parms.r_vers = version;
585 1.3.4.2 minoura if (nconf)
586 1.3.4.2 minoura parms.r_netid = nconf->nc_netid;
587 1.3.4.2 minoura else
588 1.3.4.2 minoura parms.r_netid = (char *) &nullstring[0]; /* unsets all */
589 1.3.4.2 minoura parms.r_addr = (char *) &nullstring[0];
590 1.3.4.2 minoura (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
591 1.3.4.2 minoura parms.r_owner = uidbuf;
592 1.3.4.2 minoura
593 1.3.4.2 minoura CLNT_CALL(client, RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, (char *)&parms,
594 1.3.4.2 minoura (xdrproc_t) xdr_bool, (char *)&rslt, tottimeout);
595 1.3.4.2 minoura
596 1.3.4.2 minoura CLNT_DESTROY(client);
597 1.3.4.2 minoura return (rslt);
598 1.3.4.2 minoura }
599 1.3.4.2 minoura
600 1.3.4.2 minoura /*
601 1.3.4.2 minoura * From the merged list, find the appropriate entry
602 1.3.4.2 minoura */
603 1.3.4.2 minoura static struct netbuf *
604 1.3.4.2 minoura got_entry(relp, nconf)
605 1.3.4.2 minoura rpcb_entry_list_ptr relp;
606 1.3.4.2 minoura const struct netconfig *nconf;
607 1.3.4.2 minoura {
608 1.3.4.2 minoura struct netbuf *na = NULL;
609 1.3.4.2 minoura rpcb_entry_list_ptr sp;
610 1.3.4.2 minoura rpcb_entry *rmap;
611 1.3.4.2 minoura
612 1.3.4.2 minoura for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
613 1.3.4.2 minoura rmap = &sp->rpcb_entry_map;
614 1.3.4.2 minoura if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
615 1.3.4.2 minoura (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
616 1.3.4.2 minoura (nconf->nc_semantics == rmap->r_nc_semantics) &&
617 1.3.4.2 minoura (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != NULL)) {
618 1.3.4.2 minoura na = uaddr2taddr(nconf, rmap->r_maddr);
619 1.3.4.2 minoura #ifdef ND_DEBUG
620 1.3.4.2 minoura fprintf(stderr, "\tRemote address is [%s].\n",
621 1.3.4.2 minoura rmap->r_maddr);
622 1.3.4.2 minoura if (!na)
623 1.3.4.2 minoura fprintf(stderr,
624 1.3.4.2 minoura "\tCouldn't resolve remote address!\n");
625 1.3.4.2 minoura #endif
626 1.3.4.2 minoura break;
627 1.3.4.2 minoura }
628 1.3.4.2 minoura }
629 1.3.4.2 minoura return (na);
630 1.3.4.2 minoura }
631 1.3.4.2 minoura
632 1.3.4.2 minoura /*
633 1.3.4.2 minoura * An internal function which optimizes rpcb_getaddr function. It also
634 1.3.4.2 minoura * returns the client handle that it uses to contact the remote rpcbind.
635 1.3.4.2 minoura *
636 1.3.4.2 minoura * The algorithm used: If the transports is TCP or UDP, it first tries
637 1.3.4.2 minoura * version 2 (portmap), 4 and then 3 (svr4). This order should be
638 1.3.4.2 minoura * changed in the next OS release to 4, 2 and 3. We are assuming that by
639 1.3.4.2 minoura * that time, version 4 would be available on many machines on the network.
640 1.3.4.2 minoura * With this algorithm, we get performance as well as a plan for
641 1.3.4.2 minoura * obsoleting version 2.
642 1.3.4.2 minoura *
643 1.3.4.2 minoura * For all other transports, the algorithm remains as 4 and then 3.
644 1.3.4.2 minoura *
645 1.3.4.2 minoura * XXX: Due to some problems with t_connect(), we do not reuse the same client
646 1.3.4.2 minoura * handle for COTS cases and hence in these cases we do not return the
647 1.3.4.2 minoura * client handle. This code will change if t_connect() ever
648 1.3.4.2 minoura * starts working properly. Also look under clnt_vc.c.
649 1.3.4.2 minoura */
650 1.3.4.2 minoura struct netbuf *
651 1.3.4.2 minoura __rpcb_findaddr(program, version, nconf, host, clpp)
652 1.3.4.2 minoura rpcprog_t program;
653 1.3.4.2 minoura rpcvers_t version;
654 1.3.4.2 minoura const struct netconfig *nconf;
655 1.3.4.2 minoura const char *host;
656 1.3.4.2 minoura CLIENT **clpp;
657 1.3.4.2 minoura {
658 1.3.4.2 minoura register CLIENT *client = NULL;
659 1.3.4.2 minoura RPCB parms;
660 1.3.4.2 minoura enum clnt_stat clnt_st;
661 1.3.4.2 minoura char *ua = NULL;
662 1.3.4.2 minoura rpcvers_t vers;
663 1.3.4.2 minoura struct netbuf *address = NULL;
664 1.3.4.2 minoura rpcvers_t start_vers = RPCBVERS4;
665 1.3.4.2 minoura struct netbuf servaddr;
666 1.3.4.2 minoura
667 1.3.4.2 minoura /* parameter checking */
668 1.3.4.2 minoura if (nconf == (struct netconfig *)NULL) {
669 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
670 1.3.4.2 minoura return (NULL);
671 1.3.4.2 minoura }
672 1.3.4.2 minoura
673 1.3.4.2 minoura parms.r_addr = NULL;
674 1.3.4.2 minoura
675 1.3.4.2 minoura #ifdef PORTMAP
676 1.3.4.2 minoura /* Try version 2 for TCP or UDP */
677 1.3.4.2 minoura if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
678 1.3.4.2 minoura u_short port = 0;
679 1.3.4.2 minoura struct netbuf remote;
680 1.3.4.2 minoura u_long pmapvers = 2;
681 1.3.4.2 minoura struct pmap pmapparms;
682 1.3.4.2 minoura
683 1.3.4.2 minoura /*
684 1.3.4.2 minoura * Try UDP only - there are some portmappers out
685 1.3.4.2 minoura * there that use UDP only.
686 1.3.4.2 minoura */
687 1.3.4.2 minoura if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
688 1.3.4.2 minoura struct netconfig *newnconf;
689 1.3.4.2 minoura
690 1.3.4.2 minoura if ((newnconf = getnetconfigent("udp")) == NULL) {
691 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
692 1.3.4.2 minoura return (NULL);
693 1.3.4.2 minoura }
694 1.3.4.2 minoura client = getclnthandle(host, newnconf, &parms.r_addr);
695 1.3.4.2 minoura freenetconfigent(newnconf);
696 1.3.4.2 minoura } else {
697 1.3.4.2 minoura client = getclnthandle(host, nconf, &parms.r_addr);
698 1.3.4.2 minoura }
699 1.3.4.2 minoura if (client == (CLIENT *)NULL) {
700 1.3.4.2 minoura return (NULL);
701 1.3.4.2 minoura }
702 1.3.4.2 minoura
703 1.3.4.2 minoura /* Set the version */
704 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
705 1.3.4.2 minoura pmapparms.pm_prog = program;
706 1.3.4.2 minoura pmapparms.pm_vers = version;
707 1.3.4.2 minoura pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
708 1.3.4.2 minoura IPPROTO_UDP : IPPROTO_TCP;
709 1.3.4.2 minoura pmapparms.pm_port = 0; /* not needed */
710 1.3.4.2 minoura clnt_st = CLNT_CALL(client, PMAPPROC_GETPORT,
711 1.3.4.2 minoura (xdrproc_t) xdr_pmap, (caddr_t) &pmapparms,
712 1.3.4.2 minoura (xdrproc_t) xdr_u_short, (caddr_t) &port,
713 1.3.4.2 minoura tottimeout);
714 1.3.4.2 minoura if (clnt_st != RPC_SUCCESS) {
715 1.3.4.2 minoura if ((clnt_st == RPC_PROGVERSMISMATCH) ||
716 1.3.4.2 minoura (clnt_st == RPC_PROGUNAVAIL))
717 1.3.4.2 minoura goto try_rpcbind; /* Try different versions */
718 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_PMAPFAILURE;
719 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
720 1.3.4.2 minoura goto error;
721 1.3.4.2 minoura } else if (port == 0) {
722 1.3.4.2 minoura address = NULL;
723 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
724 1.3.4.2 minoura goto error;
725 1.3.4.2 minoura }
726 1.3.4.2 minoura port = htons(port);
727 1.3.4.2 minoura CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
728 1.3.4.2 minoura if (((address = (struct netbuf *)
729 1.3.4.2 minoura malloc(sizeof (struct netbuf))) == NULL) ||
730 1.3.4.2 minoura ((address->buf = (char *)
731 1.3.4.2 minoura malloc(remote.len)) == NULL)) {
732 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_SYSTEMERROR;
733 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
734 1.3.4.2 minoura if (address) {
735 1.3.4.2 minoura free(address);
736 1.3.4.2 minoura address = NULL;
737 1.3.4.2 minoura }
738 1.3.4.2 minoura goto error;
739 1.3.4.2 minoura }
740 1.3.4.2 minoura memcpy(address->buf, remote.buf, remote.len);
741 1.3.4.2 minoura memcpy(&((char *)address->buf)[sizeof (short)],
742 1.3.4.2 minoura (char *)&port, sizeof (short));
743 1.3.4.2 minoura address->len = address->maxlen = remote.len;
744 1.3.4.2 minoura goto done;
745 1.3.4.2 minoura }
746 1.3.4.2 minoura #endif
747 1.3.4.2 minoura
748 1.3.4.2 minoura try_rpcbind:
749 1.3.4.2 minoura /*
750 1.3.4.2 minoura * Now we try version 4 and then 3.
751 1.3.4.2 minoura * We also send the remote system the address we used to
752 1.3.4.2 minoura * contact it in case it can help to connect back with us
753 1.3.4.2 minoura */
754 1.3.4.2 minoura parms.r_prog = program;
755 1.3.4.2 minoura parms.r_vers = version;
756 1.3.4.2 minoura parms.r_owner = (char *) &nullstring[0]; /* not needed; */
757 1.3.4.2 minoura /* just for xdring */
758 1.3.4.2 minoura parms.r_netid = nconf->nc_netid; /* not really needed */
759 1.3.4.2 minoura
760 1.3.4.2 minoura /*
761 1.3.4.2 minoura * If a COTS transport is being used, try getting address via CLTS
762 1.3.4.2 minoura * transport. This works only with version 4.
763 1.3.4.2 minoura * NOTE: This is being done for all transports EXCEPT LOOPBACK
764 1.3.4.2 minoura * because with loopback the cost to go to a COTS is same as
765 1.3.4.2 minoura * the cost to go through CLTS, plus you get the advantage of
766 1.3.4.2 minoura * finding out immediately if the local rpcbind process is dead.
767 1.3.4.2 minoura */
768 1.3.4.2 minoura #if 1
769 1.3.4.2 minoura if ((nconf->nc_semantics == NC_TPI_COTS_ORD ||
770 1.3.4.2 minoura nconf->nc_semantics == NC_TPI_COTS) &&
771 1.3.4.2 minoura (strcmp(nconf->nc_protofmly, NC_LOOPBACK) != 0)) {
772 1.3.4.2 minoura #else
773 1.3.4.2 minoura if (client != NULL) {
774 1.3.4.2 minoura CLNT_DESTROY(client);
775 1.3.4.2 minoura client = NULL;
776 1.3.4.2 minoura }
777 1.3.4.2 minoura if (nconf->nc_semantics == NC_TPI_CLTS) {
778 1.3.4.2 minoura #endif
779 1.3.4.2 minoura void *handle;
780 1.3.4.2 minoura struct netconfig *nconf_clts;
781 1.3.4.2 minoura rpcb_entry_list_ptr relp = NULL;
782 1.3.4.2 minoura
783 1.3.4.2 minoura if (client == NULL) {
784 1.3.4.2 minoura /* This did not go through the above PORTMAP/TCP code */
785 1.3.4.2 minoura #if 1
786 1.3.4.2 minoura if ((handle = __rpc_setconf("datagram_v")) != NULL) {
787 1.3.4.2 minoura #else
788 1.3.4.2 minoura if ((handle = __rpc_setconf("circuit_v")) != NULL) {
789 1.3.4.2 minoura #endif
790 1.3.4.2 minoura while ((nconf_clts = __rpc_getconf(handle))
791 1.3.4.2 minoura != NULL) {
792 1.3.4.2 minoura if (strcmp(nconf_clts->nc_protofmly,
793 1.3.4.2 minoura nconf->nc_protofmly) != 0) {
794 1.3.4.2 minoura continue;
795 1.3.4.2 minoura }
796 1.3.4.2 minoura client = getclnthandle(host, nconf_clts,
797 1.3.4.2 minoura &parms.r_addr);
798 1.3.4.2 minoura break;
799 1.3.4.2 minoura }
800 1.3.4.2 minoura __rpc_endconf(handle);
801 1.3.4.2 minoura }
802 1.3.4.2 minoura if (client == (CLIENT *)NULL)
803 1.3.4.2 minoura goto regular_rpcbind; /* Go the regular way */
804 1.3.4.2 minoura } else {
805 1.3.4.2 minoura /* This is a UDP PORTMAP handle. Change to version 4 */
806 1.3.4.2 minoura vers = RPCBVERS4;
807 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
808 1.3.4.2 minoura }
809 1.3.4.2 minoura /*
810 1.3.4.2 minoura * We also send the remote system the address we used to
811 1.3.4.2 minoura * contact it in case it can help it connect back with us
812 1.3.4.2 minoura */
813 1.3.4.2 minoura if (parms.r_addr == NULL)
814 1.3.4.2 minoura parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
815 1.3.4.2 minoura clnt_st = CLNT_CALL(client, RPCBPROC_GETADDRLIST,
816 1.3.4.2 minoura (xdrproc_t) xdr_rpcb, (char *) &parms,
817 1.3.4.2 minoura (xdrproc_t) xdr_rpcb_entry_list_ptr,
818 1.3.4.2 minoura (char *) &relp, tottimeout);
819 1.3.4.2 minoura if (clnt_st == RPC_SUCCESS) {
820 1.3.4.2 minoura if ((address = got_entry(relp, nconf))) {
821 1.3.4.2 minoura xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
822 1.3.4.2 minoura (char *)&relp);
823 1.3.4.2 minoura goto done;
824 1.3.4.2 minoura }
825 1.3.4.2 minoura /* Entry not found for this transport */
826 1.3.4.2 minoura xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
827 1.3.4.2 minoura (char *)&relp);
828 1.3.4.2 minoura /*
829 1.3.4.2 minoura * XXX: should have perhaps returned with error but
830 1.3.4.2 minoura * since the remote machine might not always be able
831 1.3.4.2 minoura * to send the address on all transports, we try the
832 1.3.4.2 minoura * regular way with regular_rpcbind
833 1.3.4.2 minoura */
834 1.3.4.2 minoura goto regular_rpcbind;
835 1.3.4.2 minoura } else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
836 1.3.4.2 minoura (clnt_st == RPC_PROGUNAVAIL)) {
837 1.3.4.2 minoura start_vers = RPCBVERS; /* Try version 3 now */
838 1.3.4.2 minoura goto regular_rpcbind; /* Try different versions */
839 1.3.4.2 minoura } else {
840 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_PMAPFAILURE;
841 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
842 1.3.4.2 minoura goto error;
843 1.3.4.2 minoura }
844 1.3.4.2 minoura }
845 1.3.4.2 minoura
846 1.3.4.2 minoura regular_rpcbind:
847 1.3.4.2 minoura
848 1.3.4.2 minoura /* Now the same transport is to be used to get the address */
849 1.3.4.2 minoura #if 1
850 1.3.4.2 minoura if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
851 1.3.4.2 minoura (nconf->nc_semantics == NC_TPI_COTS))) {
852 1.3.4.2 minoura #else
853 1.3.4.2 minoura if (client && nconf->nc_semantics == NC_TPI_CLTS) {
854 1.3.4.2 minoura #endif
855 1.3.4.2 minoura /* A CLTS type of client - destroy it */
856 1.3.4.2 minoura CLNT_DESTROY(client);
857 1.3.4.2 minoura client = NULL;
858 1.3.4.2 minoura }
859 1.3.4.2 minoura
860 1.3.4.2 minoura if (client == NULL) {
861 1.3.4.2 minoura client = getclnthandle(host, nconf, &parms.r_addr);
862 1.3.4.2 minoura if (client == NULL) {
863 1.3.4.2 minoura goto error;
864 1.3.4.2 minoura }
865 1.3.4.2 minoura }
866 1.3.4.2 minoura if (parms.r_addr == NULL)
867 1.3.4.2 minoura parms.r_addr = (char *) &nullstring[0];
868 1.3.4.2 minoura
869 1.3.4.2 minoura /* First try from start_vers and then version 3 (RPCBVERS) */
870 1.3.4.2 minoura for (vers = start_vers; vers >= RPCBVERS; vers--) {
871 1.3.4.2 minoura /* Set the version */
872 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
873 1.3.4.2 minoura clnt_st = CLNT_CALL(client, RPCBPROC_GETADDR,
874 1.3.4.2 minoura (xdrproc_t) xdr_rpcb, (char *) &parms,
875 1.3.4.2 minoura (xdrproc_t) xdr_wrapstring,
876 1.3.4.2 minoura (char *) &ua, tottimeout);
877 1.3.4.2 minoura if (clnt_st == RPC_SUCCESS) {
878 1.3.4.2 minoura if ((ua == NULL) || (ua[0] == NULL)) {
879 1.3.4.2 minoura /* address unknown */
880 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
881 1.3.4.2 minoura goto error;
882 1.3.4.2 minoura }
883 1.3.4.2 minoura address = uaddr2taddr(nconf, ua);
884 1.3.4.2 minoura #ifdef ND_DEBUG
885 1.3.4.2 minoura fprintf(stderr, "\tRemote address is [%s]\n", ua);
886 1.3.4.2 minoura if (!address)
887 1.3.4.2 minoura fprintf(stderr,
888 1.3.4.2 minoura "\tCouldn't resolve remote address!\n");
889 1.3.4.2 minoura #endif
890 1.3.4.2 minoura xdr_free((xdrproc_t)xdr_wrapstring, (char *)&ua);
891 1.3.4.2 minoura
892 1.3.4.2 minoura if (! address) {
893 1.3.4.2 minoura /* We don't know about your universal address */
894 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
895 1.3.4.2 minoura goto error;
896 1.3.4.2 minoura }
897 1.3.4.2 minoura CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&servaddr);
898 1.3.4.2 minoura __rpc_fixup_addr(address, &servaddr);
899 1.3.4.2 minoura goto done;
900 1.3.4.2 minoura } else if (clnt_st == RPC_PROGVERSMISMATCH) {
901 1.3.4.2 minoura struct rpc_err rpcerr;
902 1.3.4.2 minoura
903 1.3.4.2 minoura clnt_geterr(client, &rpcerr);
904 1.3.4.2 minoura if (rpcerr.re_vers.low > RPCBVERS4)
905 1.3.4.2 minoura goto error; /* a new version, can't handle */
906 1.3.4.2 minoura } else if (clnt_st != RPC_PROGUNAVAIL) {
907 1.3.4.2 minoura /* Cant handle this error */
908 1.3.4.2 minoura rpc_createerr.cf_stat = clnt_st;
909 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
910 1.3.4.2 minoura goto error;
911 1.3.4.2 minoura }
912 1.3.4.2 minoura }
913 1.3.4.2 minoura
914 1.3.4.2 minoura if ((address == NULL) || (address->len == 0)) {
915 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
916 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
917 1.3.4.2 minoura }
918 1.3.4.2 minoura
919 1.3.4.2 minoura error:
920 1.3.4.2 minoura if (client) {
921 1.3.4.2 minoura CLNT_DESTROY(client);
922 1.3.4.2 minoura client = NULL;
923 1.3.4.2 minoura }
924 1.3.4.2 minoura done:
925 1.3.4.2 minoura if (nconf->nc_semantics != NC_TPI_CLTS) {
926 1.3.4.2 minoura /* This client is the connectionless one */
927 1.3.4.2 minoura if (client) {
928 1.3.4.2 minoura CLNT_DESTROY(client);
929 1.3.4.2 minoura client = NULL;
930 1.3.4.2 minoura }
931 1.3.4.2 minoura }
932 1.3.4.2 minoura if (clpp) {
933 1.3.4.2 minoura *clpp = client;
934 1.3.4.2 minoura } else if (client) {
935 1.3.4.2 minoura CLNT_DESTROY(client);
936 1.3.4.2 minoura }
937 1.3.4.2 minoura return (address);
938 1.3.4.2 minoura }
939 1.3.4.2 minoura
940 1.3.4.2 minoura
941 1.3.4.2 minoura /*
942 1.3.4.2 minoura * Find the mapped address for program, version.
943 1.3.4.2 minoura * Calls the rpcbind service remotely to do the lookup.
944 1.3.4.2 minoura * Uses the transport specified in nconf.
945 1.3.4.2 minoura * Returns FALSE (0) if no map exists, else returns 1.
946 1.3.4.2 minoura *
947 1.3.4.2 minoura * Assuming that the address is all properly allocated
948 1.3.4.2 minoura */
949 1.3.4.2 minoura int
950 1.3.4.2 minoura rpcb_getaddr(program, version, nconf, address, host)
951 1.3.4.2 minoura rpcprog_t program;
952 1.3.4.2 minoura rpcvers_t version;
953 1.3.4.2 minoura const struct netconfig *nconf;
954 1.3.4.2 minoura struct netbuf *address;
955 1.3.4.2 minoura const char *host;
956 1.3.4.2 minoura {
957 1.3.4.2 minoura struct netbuf *na;
958 1.3.4.2 minoura
959 1.3.4.2 minoura if ((na = __rpcb_findaddr(program, version, nconf,
960 1.3.4.2 minoura host, (CLIENT **) NULL)) == NULL)
961 1.3.4.2 minoura return (FALSE);
962 1.3.4.2 minoura
963 1.3.4.2 minoura if (na->len > address->maxlen) {
964 1.3.4.2 minoura /* Too long address */
965 1.3.4.2 minoura free(na->buf);
966 1.3.4.2 minoura free(na);
967 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_FAILED;
968 1.3.4.2 minoura return (FALSE);
969 1.3.4.2 minoura }
970 1.3.4.2 minoura memcpy(address->buf, na->buf, (int)na->len);
971 1.3.4.2 minoura address->len = na->len;
972 1.3.4.2 minoura free(na->buf);
973 1.3.4.2 minoura free(na);
974 1.3.4.2 minoura return (TRUE);
975 1.3.4.2 minoura }
976 1.3.4.2 minoura
977 1.3.4.2 minoura /*
978 1.3.4.2 minoura * Get a copy of the current maps.
979 1.3.4.2 minoura * Calls the rpcbind service remotely to get the maps.
980 1.3.4.2 minoura *
981 1.3.4.2 minoura * It returns only a list of the services
982 1.3.4.2 minoura * It returns NULL on failure.
983 1.3.4.2 minoura */
984 1.3.4.2 minoura rpcblist *
985 1.3.4.2 minoura rpcb_getmaps(nconf, host)
986 1.3.4.2 minoura const struct netconfig *nconf;
987 1.3.4.2 minoura const char *host;
988 1.3.4.2 minoura {
989 1.3.4.2 minoura rpcblist_ptr head = (rpcblist_ptr)NULL;
990 1.3.4.2 minoura register CLIENT *client;
991 1.3.4.2 minoura enum clnt_stat clnt_st;
992 1.3.4.2 minoura long vers = 0;
993 1.3.4.2 minoura
994 1.3.4.2 minoura client = getclnthandle(host, nconf, (char **)NULL);
995 1.3.4.2 minoura if (client == (CLIENT *)NULL) {
996 1.3.4.2 minoura return (head);
997 1.3.4.2 minoura }
998 1.3.4.2 minoura clnt_st = CLNT_CALL(client, RPCBPROC_DUMP,
999 1.3.4.2 minoura (xdrproc_t) xdr_void, NULL,
1000 1.3.4.2 minoura (xdrproc_t) xdr_rpcblist_ptr,
1001 1.3.4.2 minoura (char *)&head, tottimeout);
1002 1.3.4.2 minoura if (clnt_st == RPC_SUCCESS)
1003 1.3.4.2 minoura goto done;
1004 1.3.4.2 minoura
1005 1.3.4.2 minoura if ((clnt_st != RPC_PROGVERSMISMATCH) &&
1006 1.3.4.2 minoura (clnt_st != RPC_PROGUNAVAIL)) {
1007 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1008 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
1009 1.3.4.2 minoura goto done;
1010 1.3.4.2 minoura }
1011 1.3.4.2 minoura
1012 1.3.4.2 minoura /* fall back to earlier version */
1013 1.3.4.2 minoura CLNT_CONTROL(client, CLGET_VERS, (char *)&vers);
1014 1.3.4.2 minoura if (vers == RPCBVERS4) {
1015 1.3.4.2 minoura vers = RPCBVERS;
1016 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
1017 1.3.4.2 minoura if (CLNT_CALL(client, RPCBPROC_DUMP,
1018 1.3.4.2 minoura (xdrproc_t) xdr_void,
1019 1.3.4.2 minoura (char *) NULL, (xdrproc_t) xdr_rpcblist_ptr,
1020 1.3.4.2 minoura (char *)&head, tottimeout) == RPC_SUCCESS)
1021 1.3.4.2 minoura goto done;
1022 1.3.4.2 minoura }
1023 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_RPCBFAILURE;
1024 1.3.4.2 minoura clnt_geterr(client, &rpc_createerr.cf_error);
1025 1.3.4.2 minoura
1026 1.3.4.2 minoura done:
1027 1.3.4.2 minoura CLNT_DESTROY(client);
1028 1.3.4.2 minoura return (head);
1029 1.3.4.2 minoura }
1030 1.3.4.2 minoura
1031 1.3.4.2 minoura /*
1032 1.3.4.2 minoura * rpcbinder remote-call-service interface.
1033 1.3.4.2 minoura * This routine is used to call the rpcbind remote call service
1034 1.3.4.2 minoura * which will look up a service program in the address maps, and then
1035 1.3.4.2 minoura * remotely call that routine with the given parameters. This allows
1036 1.3.4.2 minoura * programs to do a lookup and call in one step.
1037 1.3.4.2 minoura */
1038 1.3.4.2 minoura enum clnt_stat
1039 1.3.4.2 minoura rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
1040 1.3.4.2 minoura xdrres, resp, tout, addr_ptr)
1041 1.3.4.2 minoura const struct netconfig *nconf; /* Netconfig structure */
1042 1.3.4.2 minoura const char *host; /* Remote host name */
1043 1.3.4.2 minoura rpcprog_t prog;
1044 1.3.4.2 minoura rpcvers_t vers;
1045 1.3.4.2 minoura rpcproc_t proc; /* Remote proc identifiers */
1046 1.3.4.2 minoura xdrproc_t xdrargs, xdrres; /* XDR routines */
1047 1.3.4.2 minoura caddr_t argsp, resp; /* Argument and Result */
1048 1.3.4.2 minoura struct timeval tout; /* Timeout value for this call */
1049 1.3.4.2 minoura const struct netbuf *addr_ptr; /* Preallocated netbuf address */
1050 1.3.4.2 minoura {
1051 1.3.4.2 minoura register CLIENT *client;
1052 1.3.4.2 minoura enum clnt_stat stat;
1053 1.3.4.2 minoura struct r_rpcb_rmtcallargs a;
1054 1.3.4.2 minoura struct r_rpcb_rmtcallres r;
1055 1.3.4.2 minoura long rpcb_vers;
1056 1.3.4.2 minoura
1057 1.3.4.2 minoura
1058 1.3.4.2 minoura client = getclnthandle(host, nconf, (char **)NULL);
1059 1.3.4.2 minoura if (client == (CLIENT *)NULL) {
1060 1.3.4.2 minoura return (RPC_FAILED);
1061 1.3.4.2 minoura }
1062 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rmttimeout);
1063 1.3.4.2 minoura a.prog = prog;
1064 1.3.4.2 minoura a.vers = vers;
1065 1.3.4.2 minoura a.proc = proc;
1066 1.3.4.2 minoura a.args.args_val = argsp;
1067 1.3.4.2 minoura a.xdr_args = xdrargs;
1068 1.3.4.2 minoura r.addr = NULL;
1069 1.3.4.2 minoura r.results.results_val = resp;
1070 1.3.4.2 minoura r.xdr_res = xdrres;
1071 1.3.4.2 minoura
1072 1.3.4.2 minoura for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
1073 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&rpcb_vers);
1074 1.3.4.2 minoura stat = CLNT_CALL(client, RPCBPROC_CALLIT,
1075 1.3.4.2 minoura (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)&a,
1076 1.3.4.2 minoura (xdrproc_t) xdr_rpcb_rmtcallres, (char *)&r, tout);
1077 1.3.4.2 minoura if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
1078 1.3.4.2 minoura struct netbuf *na;
1079 1.3.4.2 minoura
1080 1.3.4.2 minoura na = uaddr2taddr((struct netconfig *) nconf, r.addr);
1081 1.3.4.2 minoura if (! na) {
1082 1.3.4.2 minoura stat = RPC_N2AXLATEFAILURE;
1083 1.3.4.2 minoura ((struct netbuf *) addr_ptr)->len = 0;
1084 1.3.4.2 minoura goto error;
1085 1.3.4.2 minoura }
1086 1.3.4.2 minoura if (na->len > addr_ptr->maxlen) {
1087 1.3.4.2 minoura /* Too long address */
1088 1.3.4.2 minoura stat = RPC_FAILED; /* XXX A better error no */
1089 1.3.4.2 minoura free(na->buf);
1090 1.3.4.2 minoura free(na);
1091 1.3.4.2 minoura ((struct netbuf *) addr_ptr)->len = 0;
1092 1.3.4.2 minoura goto error;
1093 1.3.4.2 minoura }
1094 1.3.4.2 minoura memcpy(addr_ptr->buf, na->buf, (int)na->len);
1095 1.3.4.2 minoura ((struct netbuf *)addr_ptr)->len = na->len;
1096 1.3.4.2 minoura free(na->buf);
1097 1.3.4.2 minoura free(na);
1098 1.3.4.2 minoura break;
1099 1.3.4.2 minoura } else if ((stat != RPC_PROGVERSMISMATCH) &&
1100 1.3.4.2 minoura (stat != RPC_PROGUNAVAIL)) {
1101 1.3.4.2 minoura goto error;
1102 1.3.4.2 minoura }
1103 1.3.4.2 minoura }
1104 1.3.4.2 minoura error:
1105 1.3.4.2 minoura CLNT_DESTROY(client);
1106 1.3.4.2 minoura if (r.addr)
1107 1.3.4.2 minoura xdr_free((xdrproc_t) xdr_wrapstring, (char *)&r.addr);
1108 1.3.4.2 minoura return (stat);
1109 1.3.4.2 minoura }
1110 1.3.4.2 minoura
1111 1.3.4.2 minoura /*
1112 1.3.4.2 minoura * Gets the time on the remote host.
1113 1.3.4.2 minoura * Returns 1 if succeeds else 0.
1114 1.3.4.2 minoura */
1115 1.3.4.2 minoura bool_t
1116 1.3.4.2 minoura rpcb_gettime(host, timep)
1117 1.3.4.2 minoura const char *host;
1118 1.3.4.2 minoura time_t *timep;
1119 1.3.4.2 minoura {
1120 1.3.4.2 minoura CLIENT *client = NULL;
1121 1.3.4.2 minoura void *handle;
1122 1.3.4.2 minoura struct netconfig *nconf;
1123 1.3.4.2 minoura long vers;
1124 1.3.4.2 minoura enum clnt_stat st;
1125 1.3.4.2 minoura
1126 1.3.4.2 minoura
1127 1.3.4.2 minoura if ((host == NULL) || (host[0] == NULL)) {
1128 1.3.4.2 minoura time(timep);
1129 1.3.4.2 minoura return (TRUE);
1130 1.3.4.2 minoura }
1131 1.3.4.2 minoura
1132 1.3.4.2 minoura if ((handle = __rpc_setconf("netpath")) == NULL) {
1133 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1134 1.3.4.2 minoura return (FALSE);
1135 1.3.4.2 minoura }
1136 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_SUCCESS;
1137 1.3.4.2 minoura while (client == (CLIENT *)NULL) {
1138 1.3.4.2 minoura if ((nconf = __rpc_getconf(handle)) == NULL) {
1139 1.3.4.2 minoura if (rpc_createerr.cf_stat == RPC_SUCCESS)
1140 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1141 1.3.4.2 minoura break;
1142 1.3.4.2 minoura }
1143 1.3.4.2 minoura client = getclnthandle(host, nconf, (char **)NULL);
1144 1.3.4.2 minoura if (client)
1145 1.3.4.2 minoura break;
1146 1.3.4.2 minoura }
1147 1.3.4.2 minoura __rpc_endconf(handle);
1148 1.3.4.2 minoura if (client == (CLIENT *) NULL) {
1149 1.3.4.2 minoura return (FALSE);
1150 1.3.4.2 minoura }
1151 1.3.4.2 minoura
1152 1.3.4.2 minoura st = CLNT_CALL(client, RPCBPROC_GETTIME,
1153 1.3.4.2 minoura (xdrproc_t) xdr_void, (char *)NULL,
1154 1.3.4.2 minoura (xdrproc_t) xdr_int, (char *)timep, tottimeout);
1155 1.3.4.2 minoura
1156 1.3.4.2 minoura if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
1157 1.3.4.2 minoura CLNT_CONTROL(client, CLGET_VERS, (char *)&vers);
1158 1.3.4.2 minoura if (vers == RPCBVERS4) {
1159 1.3.4.2 minoura /* fall back to earlier version */
1160 1.3.4.2 minoura vers = RPCBVERS;
1161 1.3.4.2 minoura CLNT_CONTROL(client, CLSET_VERS, (char *)&vers);
1162 1.3.4.2 minoura st = CLNT_CALL(client, RPCBPROC_GETTIME,
1163 1.3.4.2 minoura (xdrproc_t) xdr_void, (char *)NULL,
1164 1.3.4.2 minoura (xdrproc_t) xdr_int, (char *) timep,
1165 1.3.4.2 minoura tottimeout);
1166 1.3.4.2 minoura }
1167 1.3.4.2 minoura }
1168 1.3.4.2 minoura CLNT_DESTROY(client);
1169 1.3.4.2 minoura return (st == RPC_SUCCESS? TRUE: FALSE);
1170 1.3.4.2 minoura }
1171 1.3.4.2 minoura
1172 1.3.4.2 minoura /*
1173 1.3.4.2 minoura * Converts taddr to universal address. This routine should never
1174 1.3.4.2 minoura * really be called because local n2a libraries are always provided.
1175 1.3.4.2 minoura */
1176 1.3.4.2 minoura char *
1177 1.3.4.2 minoura rpcb_taddr2uaddr(nconf, taddr)
1178 1.3.4.2 minoura struct netconfig *nconf;
1179 1.3.4.2 minoura struct netbuf *taddr;
1180 1.3.4.2 minoura {
1181 1.3.4.2 minoura CLIENT *client;
1182 1.3.4.2 minoura char *uaddr = NULL;
1183 1.3.4.2 minoura
1184 1.3.4.2 minoura
1185 1.3.4.2 minoura /* parameter checking */
1186 1.3.4.2 minoura if (nconf == (struct netconfig *)NULL) {
1187 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1188 1.3.4.2 minoura return (NULL);
1189 1.3.4.2 minoura }
1190 1.3.4.2 minoura if (taddr == NULL) {
1191 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1192 1.3.4.2 minoura return (NULL);
1193 1.3.4.2 minoura }
1194 1.3.4.2 minoura client = local_rpcb();
1195 1.3.4.2 minoura if (! client) {
1196 1.3.4.2 minoura return (NULL);
1197 1.3.4.2 minoura }
1198 1.3.4.2 minoura
1199 1.3.4.2 minoura CLNT_CALL(client, RPCBPROC_TADDR2UADDR, (xdrproc_t) xdr_netbuf,
1200 1.3.4.2 minoura (char *)taddr, (xdrproc_t) xdr_wrapstring, (char *)&uaddr,
1201 1.3.4.2 minoura tottimeout);
1202 1.3.4.2 minoura CLNT_DESTROY(client);
1203 1.3.4.2 minoura return (uaddr);
1204 1.3.4.2 minoura }
1205 1.3.4.2 minoura
1206 1.3.4.2 minoura /*
1207 1.3.4.2 minoura * Converts universal address to netbuf. This routine should never
1208 1.3.4.2 minoura * really be called because local n2a libraries are always provided.
1209 1.3.4.2 minoura */
1210 1.3.4.2 minoura struct netbuf *
1211 1.3.4.2 minoura rpcb_uaddr2taddr(nconf, uaddr)
1212 1.3.4.2 minoura struct netconfig *nconf;
1213 1.3.4.2 minoura char *uaddr;
1214 1.3.4.2 minoura {
1215 1.3.4.2 minoura CLIENT *client;
1216 1.3.4.2 minoura struct netbuf *taddr;
1217 1.3.4.2 minoura
1218 1.3.4.2 minoura
1219 1.3.4.2 minoura /* parameter checking */
1220 1.3.4.2 minoura if (nconf == (struct netconfig *)NULL) {
1221 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
1222 1.3.4.2 minoura return (NULL);
1223 1.3.4.2 minoura }
1224 1.3.4.2 minoura if (uaddr == NULL) {
1225 1.3.4.2 minoura rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
1226 1.3.4.2 minoura return (NULL);
1227 1.3.4.2 minoura }
1228 1.3.4.2 minoura client = local_rpcb();
1229 1.3.4.2 minoura if (! client) {
1230 1.3.4.2 minoura return (NULL);
1231 1.3.4.2 minoura }
1232 1.3.4.2 minoura
1233 1.3.4.2 minoura taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
1234 1.3.4.2 minoura if (taddr == NULL) {
1235 1.3.4.2 minoura CLNT_DESTROY(client);
1236 1.3.4.2 minoura return (NULL);
1237 1.3.4.2 minoura }
1238 1.3.4.2 minoura if (CLNT_CALL(client, RPCBPROC_UADDR2TADDR, (xdrproc_t) xdr_wrapstring,
1239 1.3.4.2 minoura (char *) &uaddr, (xdrproc_t) xdr_netbuf, (char *)taddr,
1240 1.3.4.2 minoura tottimeout) != RPC_SUCCESS) {
1241 1.3.4.2 minoura free(taddr);
1242 1.3.4.2 minoura taddr = NULL;
1243 1.3.4.2 minoura }
1244 1.3.4.2 minoura CLNT_DESTROY(client);
1245 1.3.4.2 minoura return (taddr);
1246 1.3.4.2 minoura }
1247