ypbind.c revision 1.20 1 1.20 cgd /* $NetBSD: ypbind.c,v 1.20 1996/03/30 22:49:08 cgd Exp $ */
2 1.20 cgd
3 1.2 deraadt /*
4 1.7 deraadt * Copyright (c) 1992, 1993 Theo de Raadt <deraadt (at) fsa.ca>
5 1.2 deraadt * All rights reserved.
6 1.2 deraadt *
7 1.2 deraadt * Redistribution and use in source and binary forms, with or without
8 1.2 deraadt * modification, are permitted provided that the following conditions
9 1.2 deraadt * are met:
10 1.2 deraadt * 1. Redistributions of source code must retain the above copyright
11 1.2 deraadt * notice, this list of conditions and the following disclaimer.
12 1.2 deraadt * 2. Redistributions in binary form must reproduce the above copyright
13 1.2 deraadt * notice, this list of conditions and the following disclaimer in the
14 1.2 deraadt * documentation and/or other materials provided with the distribution.
15 1.7 deraadt * 3. All advertising materials mentioning features or use of this software
16 1.7 deraadt * must display the following acknowledgement:
17 1.7 deraadt * This product includes software developed by Theo de Raadt.
18 1.7 deraadt * 4. The name of the author may not be used to endorse or promote
19 1.2 deraadt * products derived from this software without specific prior written
20 1.2 deraadt * permission.
21 1.2 deraadt *
22 1.2 deraadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 1.2 deraadt * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 1.2 deraadt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.2 deraadt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 1.2 deraadt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.2 deraadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.2 deraadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.2 deraadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.2 deraadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.2 deraadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.2 deraadt * SUCH DAMAGE.
33 1.2 deraadt */
34 1.2 deraadt
35 1.2 deraadt #ifndef LINT
36 1.20 cgd static char rcsid[] = "$NetBSD: ypbind.c,v 1.20 1996/03/30 22:49:08 cgd Exp $";
37 1.2 deraadt #endif
38 1.2 deraadt
39 1.1 deraadt #include <sys/param.h>
40 1.1 deraadt #include <sys/types.h>
41 1.1 deraadt #include <sys/ioctl.h>
42 1.1 deraadt #include <sys/signal.h>
43 1.1 deraadt #include <sys/socket.h>
44 1.1 deraadt #include <sys/file.h>
45 1.1 deraadt #include <sys/fcntl.h>
46 1.6 deraadt #include <sys/uio.h>
47 1.1 deraadt #include <sys/syslog.h>
48 1.1 deraadt #include <stdio.h>
49 1.14 cgd #include <stdlib.h>
50 1.1 deraadt #include <errno.h>
51 1.1 deraadt #include <ctype.h>
52 1.1 deraadt #include <dirent.h>
53 1.1 deraadt #include <netdb.h>
54 1.1 deraadt #include <string.h>
55 1.1 deraadt #include <rpc/rpc.h>
56 1.1 deraadt #include <rpc/xdr.h>
57 1.1 deraadt #include <net/if.h>
58 1.1 deraadt #include <arpa/inet.h>
59 1.1 deraadt #include <rpc/pmap_clnt.h>
60 1.1 deraadt #include <rpc/pmap_prot.h>
61 1.1 deraadt #include <rpc/pmap_rmt.h>
62 1.1 deraadt #include <unistd.h>
63 1.1 deraadt #include <rpcsvc/yp_prot.h>
64 1.1 deraadt #include <rpcsvc/ypclnt.h>
65 1.1 deraadt
66 1.13 deraadt #define BINDINGDIR "/var/yp/binding"
67 1.13 deraadt #define YPBINDLOCK "/var/run/ypbind.lock"
68 1.1 deraadt
69 1.1 deraadt struct _dom_binding {
70 1.1 deraadt struct _dom_binding *dom_pnext;
71 1.1 deraadt char dom_domain[YPMAXDOMAIN + 1];
72 1.1 deraadt struct sockaddr_in dom_server_addr;
73 1.1 deraadt unsigned short int dom_server_port;
74 1.1 deraadt int dom_socket;
75 1.1 deraadt CLIENT *dom_client;
76 1.1 deraadt long int dom_vers;
77 1.1 deraadt time_t dom_check_t;
78 1.9 deraadt time_t dom_ask_t;
79 1.1 deraadt int dom_lockfd;
80 1.1 deraadt int dom_alive;
81 1.20 cgd int dom_xid;
82 1.1 deraadt };
83 1.1 deraadt
84 1.1 deraadt extern bool_t xdr_domainname(), xdr_ypbind_resp();
85 1.1 deraadt extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
86 1.1 deraadt extern bool_t xdr_ypbind_setdom();
87 1.1 deraadt
88 1.1 deraadt char *domainname;
89 1.1 deraadt
90 1.1 deraadt struct _dom_binding *ypbindlist;
91 1.1 deraadt int check;
92 1.1 deraadt
93 1.1 deraadt #define YPSET_NO 0
94 1.1 deraadt #define YPSET_LOCAL 1
95 1.1 deraadt #define YPSET_ALL 2
96 1.1 deraadt int ypsetmode = YPSET_NO;
97 1.1 deraadt
98 1.10 deraadt int rpcsock, pingsock;
99 1.1 deraadt struct rmtcallargs rmtca;
100 1.1 deraadt struct rmtcallres rmtcr;
101 1.1 deraadt char rmtcr_outval;
102 1.1 deraadt u_long rmtcr_port;
103 1.6 deraadt SVCXPRT *udptransp, *tcptransp;
104 1.1 deraadt
105 1.20 cgd struct _dom_binding *xid2ypdb __P((int xid));
106 1.20 cgd int unique_xid __P((struct _dom_binding *ypdb));
107 1.20 cgd
108 1.1 deraadt void *
109 1.1 deraadt ypbindproc_null_2(transp, argp, clnt)
110 1.17 mycroft SVCXPRT *transp;
111 1.17 mycroft void *argp;
112 1.17 mycroft CLIENT *clnt;
113 1.1 deraadt {
114 1.1 deraadt static char res;
115 1.1 deraadt
116 1.17 mycroft memset(&res, 0, sizeof(res));
117 1.1 deraadt return (void *)&res;
118 1.1 deraadt }
119 1.1 deraadt
120 1.1 deraadt struct ypbind_resp *
121 1.1 deraadt ypbindproc_domain_2(transp, argp, clnt)
122 1.17 mycroft SVCXPRT *transp;
123 1.17 mycroft char *argp;
124 1.17 mycroft CLIENT *clnt;
125 1.1 deraadt {
126 1.1 deraadt static struct ypbind_resp res;
127 1.1 deraadt struct _dom_binding *ypdb;
128 1.1 deraadt char path[MAXPATHLEN];
129 1.9 deraadt time_t now;
130 1.1 deraadt
131 1.17 mycroft memset(&res, 0, sizeof res);
132 1.1 deraadt res.ypbind_status = YPBIND_FAIL_VAL;
133 1.1 deraadt
134 1.17 mycroft for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
135 1.17 mycroft if (!strcmp(ypdb->dom_domain, argp))
136 1.1 deraadt break;
137 1.1 deraadt
138 1.17 mycroft if (ypdb == NULL) {
139 1.1 deraadt ypdb = (struct _dom_binding *)malloc(sizeof *ypdb);
140 1.17 mycroft memset(ypdb, 0, sizeof *ypdb);
141 1.1 deraadt strncpy(ypdb->dom_domain, argp, sizeof ypdb->dom_domain);
142 1.1 deraadt ypdb->dom_vers = YPVERS;
143 1.1 deraadt ypdb->dom_alive = 0;
144 1.1 deraadt ypdb->dom_lockfd = -1;
145 1.1 deraadt sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers);
146 1.1 deraadt unlink(path);
147 1.20 cgd ypdb->dom_xid = unique_xid(ypdb);
148 1.1 deraadt ypdb->dom_pnext = ypbindlist;
149 1.1 deraadt ypbindlist = ypdb;
150 1.1 deraadt check++;
151 1.1 deraadt return NULL;
152 1.1 deraadt }
153 1.1 deraadt
154 1.17 mycroft if (ypdb->dom_alive == 0)
155 1.1 deraadt return NULL;
156 1.1 deraadt
157 1.9 deraadt #ifdef HEURISTIC
158 1.9 deraadt time(&now);
159 1.9 deraadt if (now < ypdb->dom_ask_t + 5) {
160 1.1 deraadt /*
161 1.9 deraadt * Hmm. More than 2 requests in 5 seconds have indicated
162 1.9 deraadt * that my binding is possibly incorrect.
163 1.9 deraadt * Ok, do an immediate poll of the server.
164 1.1 deraadt */
165 1.9 deraadt if (ypdb->dom_check_t >= now) {
166 1.9 deraadt /* don't flood it */
167 1.9 deraadt ypdb->dom_check_t = 0;
168 1.9 deraadt check++;
169 1.9 deraadt }
170 1.1 deraadt }
171 1.9 deraadt ypdb->dom_ask_t = now;
172 1.1 deraadt #endif
173 1.1 deraadt
174 1.1 deraadt answer:
175 1.1 deraadt res.ypbind_status = YPBIND_SUCC_VAL;
176 1.1 deraadt res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr =
177 1.1 deraadt ypdb->dom_server_addr.sin_addr.s_addr;
178 1.1 deraadt res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port =
179 1.1 deraadt ypdb->dom_server_port;
180 1.1 deraadt /*printf("domain %s at %s/%d\n", ypdb->dom_domain,
181 1.1 deraadt inet_ntoa(ypdb->dom_server_addr.sin_addr),
182 1.1 deraadt ntohs(ypdb->dom_server_addr.sin_port));*/
183 1.1 deraadt return &res;
184 1.1 deraadt }
185 1.1 deraadt
186 1.1 deraadt bool_t *
187 1.1 deraadt ypbindproc_setdom_2(transp, argp, clnt)
188 1.17 mycroft SVCXPRT *transp;
189 1.17 mycroft struct ypbind_setdom *argp;
190 1.17 mycroft CLIENT *clnt;
191 1.1 deraadt {
192 1.1 deraadt struct sockaddr_in *fromsin, bindsin;
193 1.13 deraadt static bool_t res;
194 1.1 deraadt
195 1.17 mycroft memset(&res, 0, sizeof(res));
196 1.1 deraadt fromsin = svc_getcaller(transp);
197 1.1 deraadt
198 1.17 mycroft switch (ypsetmode) {
199 1.1 deraadt case YPSET_LOCAL:
200 1.17 mycroft if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK))
201 1.13 deraadt return (bool_t *)NULL;
202 1.1 deraadt break;
203 1.1 deraadt case YPSET_ALL:
204 1.1 deraadt break;
205 1.1 deraadt case YPSET_NO:
206 1.1 deraadt default:
207 1.13 deraadt return (bool_t *)NULL;
208 1.1 deraadt }
209 1.4 deraadt
210 1.17 mycroft if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED)
211 1.13 deraadt return &res;
212 1.1 deraadt
213 1.17 mycroft if (argp->ypsetdom_vers != YPVERS)
214 1.13 deraadt return &res;
215 1.1 deraadt
216 1.17 mycroft memset(&bindsin, 0, sizeof bindsin);
217 1.1 deraadt bindsin.sin_family = AF_INET;
218 1.17 mycroft bindsin.sin_len = sizeof(bindsin);
219 1.17 mycroft bindsin.sin_addr = argp->ypsetdom_addr;
220 1.1 deraadt bindsin.sin_port = argp->ypsetdom_port;
221 1.1 deraadt rpc_received(argp->ypsetdom_domain, &bindsin, 1);
222 1.1 deraadt
223 1.1 deraadt res = 1;
224 1.13 deraadt return &res;
225 1.1 deraadt }
226 1.1 deraadt
227 1.1 deraadt static void
228 1.1 deraadt ypbindprog_2(rqstp, transp)
229 1.17 mycroft struct svc_req *rqstp;
230 1.17 mycroft register SVCXPRT *transp;
231 1.1 deraadt {
232 1.1 deraadt union {
233 1.1 deraadt char ypbindproc_domain_2_arg[MAXHOSTNAMELEN];
234 1.1 deraadt struct ypbind_setdom ypbindproc_setdom_2_arg;
235 1.1 deraadt } argument;
236 1.1 deraadt struct authunix_parms *creds;
237 1.1 deraadt char *result;
238 1.1 deraadt bool_t (*xdr_argument)(), (*xdr_result)();
239 1.1 deraadt char *(*local)();
240 1.1 deraadt
241 1.1 deraadt switch (rqstp->rq_proc) {
242 1.1 deraadt case YPBINDPROC_NULL:
243 1.1 deraadt xdr_argument = xdr_void;
244 1.1 deraadt xdr_result = xdr_void;
245 1.1 deraadt local = (char *(*)()) ypbindproc_null_2;
246 1.1 deraadt break;
247 1.1 deraadt
248 1.1 deraadt case YPBINDPROC_DOMAIN:
249 1.1 deraadt xdr_argument = xdr_domainname;
250 1.1 deraadt xdr_result = xdr_ypbind_resp;
251 1.1 deraadt local = (char *(*)()) ypbindproc_domain_2;
252 1.1 deraadt break;
253 1.1 deraadt
254 1.1 deraadt case YPBINDPROC_SETDOM:
255 1.17 mycroft switch (rqstp->rq_cred.oa_flavor) {
256 1.1 deraadt case AUTH_UNIX:
257 1.1 deraadt creds = (struct authunix_parms *)rqstp->rq_clntcred;
258 1.17 mycroft if (creds->aup_uid != 0) {
259 1.1 deraadt svcerr_auth(transp, AUTH_BADCRED);
260 1.1 deraadt return;
261 1.1 deraadt }
262 1.1 deraadt break;
263 1.1 deraadt default:
264 1.1 deraadt svcerr_auth(transp, AUTH_TOOWEAK);
265 1.1 deraadt return;
266 1.1 deraadt }
267 1.1 deraadt
268 1.1 deraadt xdr_argument = xdr_ypbind_setdom;
269 1.1 deraadt xdr_result = xdr_void;
270 1.1 deraadt local = (char *(*)()) ypbindproc_setdom_2;
271 1.1 deraadt break;
272 1.1 deraadt
273 1.1 deraadt default:
274 1.1 deraadt svcerr_noproc(transp);
275 1.1 deraadt return;
276 1.1 deraadt }
277 1.17 mycroft memset(&argument, 0, sizeof(argument));
278 1.14 cgd if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
279 1.1 deraadt svcerr_decode(transp);
280 1.1 deraadt return;
281 1.1 deraadt }
282 1.1 deraadt result = (*local)(transp, &argument, rqstp);
283 1.1 deraadt if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
284 1.1 deraadt svcerr_systemerr(transp);
285 1.1 deraadt }
286 1.1 deraadt return;
287 1.1 deraadt }
288 1.1 deraadt
289 1.1 deraadt main(argc, argv)
290 1.17 mycroft int argc;
291 1.17 mycroft char *argv[];
292 1.1 deraadt {
293 1.1 deraadt char path[MAXPATHLEN];
294 1.1 deraadt struct timeval tv;
295 1.1 deraadt fd_set fdsr;
296 1.13 deraadt int width, lockfd;
297 1.18 mycroft int evil = 0, one;
298 1.1 deraadt
299 1.1 deraadt yp_get_default_domain(&domainname);
300 1.17 mycroft if (domainname[0] == '\0') {
301 1.1 deraadt fprintf(stderr, "domainname not set. Aborting.\n");
302 1.1 deraadt exit(1);
303 1.1 deraadt }
304 1.1 deraadt
305 1.18 mycroft while (--argc) {
306 1.18 mycroft ++argv;
307 1.18 mycroft if (!strcmp("-ypset", *argv))
308 1.1 deraadt ypsetmode = YPSET_ALL;
309 1.18 mycroft else if (!strcmp("-ypsetme", *argv))
310 1.1 deraadt ypsetmode = YPSET_LOCAL;
311 1.1 deraadt }
312 1.1 deraadt
313 1.1 deraadt /* blow away everything in BINDINGDIR */
314 1.1 deraadt
315 1.13 deraadt #ifdef O_SHLOCK
316 1.17 mycroft if ((lockfd = open(YPBINDLOCK, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) {
317 1.13 deraadt fprintf(stderr, "ypbind: cannot create %s\n", YPBINDLOCK);
318 1.13 deraadt exit(1);
319 1.13 deraadt }
320 1.13 deraadt #else
321 1.17 mycroft if ((lockfd = open(YPBINDLOCK, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) {
322 1.13 deraadt fprintf(stderr, "ypbind: cannot create %s\n", YPBINDLOCK);
323 1.13 deraadt exit(1);
324 1.13 deraadt }
325 1.13 deraadt flock(lockfd, LOCK_SH);
326 1.13 deraadt #endif
327 1.1 deraadt
328 1.18 mycroft (void)pmap_unset(YPBINDPROG, YPBINDVERS);
329 1.1 deraadt
330 1.6 deraadt udptransp = svcudp_create(RPC_ANYSOCK);
331 1.6 deraadt if (udptransp == NULL) {
332 1.1 deraadt fprintf(stderr, "cannot create udp service.");
333 1.1 deraadt exit(1);
334 1.1 deraadt }
335 1.6 deraadt if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2,
336 1.6 deraadt IPPROTO_UDP)) {
337 1.1 deraadt fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, udp).");
338 1.1 deraadt exit(1);
339 1.1 deraadt }
340 1.1 deraadt
341 1.6 deraadt tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0);
342 1.6 deraadt if (tcptransp == NULL) {
343 1.1 deraadt fprintf(stderr, "cannot create tcp service.");
344 1.1 deraadt exit(1);
345 1.1 deraadt }
346 1.6 deraadt if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2,
347 1.6 deraadt IPPROTO_TCP)) {
348 1.1 deraadt fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, tcp).");
349 1.1 deraadt exit(1);
350 1.1 deraadt }
351 1.1 deraadt
352 1.17 mycroft if ((rpcsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
353 1.1 deraadt perror("socket");
354 1.1 deraadt return -1;
355 1.1 deraadt }
356 1.17 mycroft if ((pingsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
357 1.10 deraadt perror("socket");
358 1.10 deraadt return -1;
359 1.10 deraadt }
360 1.6 deraadt
361 1.1 deraadt fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY);
362 1.10 deraadt fcntl(pingsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY);
363 1.18 mycroft one = 1;
364 1.18 mycroft setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one));
365 1.1 deraadt rmtca.prog = YPPROG;
366 1.1 deraadt rmtca.vers = YPVERS;
367 1.1 deraadt rmtca.proc = YPPROC_DOMAIN_NONACK;
368 1.1 deraadt rmtca.xdr_args = NULL; /* set at call time */
369 1.1 deraadt rmtca.args_ptr = NULL; /* set at call time */
370 1.1 deraadt rmtcr.port_ptr = &rmtcr_port;
371 1.1 deraadt rmtcr.xdr_results = xdr_bool;
372 1.1 deraadt rmtcr.results_ptr = (caddr_t)&rmtcr_outval;
373 1.1 deraadt
374 1.1 deraadt /* build initial domain binding, make it "unsuccessful" */
375 1.1 deraadt ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist);
376 1.17 mycroft memset(ypbindlist, 0, sizeof *ypbindlist);
377 1.1 deraadt strncpy(ypbindlist->dom_domain, domainname, sizeof ypbindlist->dom_domain);
378 1.1 deraadt ypbindlist->dom_vers = YPVERS;
379 1.1 deraadt ypbindlist->dom_alive = 0;
380 1.1 deraadt ypbindlist->dom_lockfd = -1;
381 1.1 deraadt sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain,
382 1.1 deraadt ypbindlist->dom_vers);
383 1.1 deraadt (void)unlink(path);
384 1.12 deraadt
385 1.12 deraadt checkwork();
386 1.1 deraadt
387 1.17 mycroft while (1) {
388 1.16 pk width = svc_maxfd;
389 1.16 pk if (rpcsock > width)
390 1.16 pk width = rpcsock;
391 1.16 pk if (pingsock > width)
392 1.16 pk width = pingsock;
393 1.16 pk width++;
394 1.17 mycroft
395 1.1 deraadt fdsr = svc_fdset;
396 1.1 deraadt FD_SET(rpcsock, &fdsr);
397 1.10 deraadt FD_SET(pingsock, &fdsr);
398 1.1 deraadt tv.tv_sec = 1;
399 1.1 deraadt tv.tv_usec = 0;
400 1.1 deraadt
401 1.17 mycroft switch (select(width, &fdsr, NULL, NULL, &tv)) {
402 1.1 deraadt case 0:
403 1.1 deraadt checkwork();
404 1.1 deraadt break;
405 1.1 deraadt case -1:
406 1.1 deraadt perror("select\n");
407 1.1 deraadt break;
408 1.1 deraadt default:
409 1.15 mycroft if (FD_ISSET(rpcsock, &fdsr))
410 1.1 deraadt handle_replies();
411 1.15 mycroft if (FD_ISSET(pingsock, &fdsr))
412 1.10 deraadt handle_ping();
413 1.1 deraadt svc_getreqset(&fdsr);
414 1.15 mycroft if (check)
415 1.1 deraadt checkwork();
416 1.1 deraadt break;
417 1.18 mycroft }
418 1.18 mycroft
419 1.18 mycroft if (!evil && ypbindlist->dom_alive) {
420 1.18 mycroft evil = 1;
421 1.18 mycroft daemon(0, 0);
422 1.1 deraadt }
423 1.1 deraadt }
424 1.1 deraadt }
425 1.1 deraadt
426 1.1 deraadt /*
427 1.9 deraadt * State transition is done like this:
428 1.9 deraadt *
429 1.11 ws * STATE EVENT ACTION NEWSTATE TIMEOUT
430 1.11 ws * no binding timeout broadcast no binding 5 sec
431 1.11 ws * no binding answer -- binding 60 sec
432 1.11 ws * binding timeout ping server checking 5 sec
433 1.11 ws * checking timeout ping server + broadcast checking 5 sec
434 1.11 ws * checking answer -- binding 60 sec
435 1.1 deraadt */
436 1.1 deraadt checkwork()
437 1.1 deraadt {
438 1.1 deraadt struct _dom_binding *ypdb;
439 1.1 deraadt time_t t;
440 1.1 deraadt
441 1.1 deraadt check = 0;
442 1.1 deraadt
443 1.1 deraadt time(&t);
444 1.17 mycroft for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) {
445 1.17 mycroft if (ypdb->dom_check_t < t) {
446 1.10 deraadt if (ypdb->dom_alive == 1)
447 1.10 deraadt ping(ypdb);
448 1.10 deraadt else
449 1.10 deraadt broadcast(ypdb);
450 1.1 deraadt time(&t);
451 1.1 deraadt ypdb->dom_check_t = t + 5;
452 1.1 deraadt }
453 1.1 deraadt }
454 1.1 deraadt }
455 1.1 deraadt
456 1.8 deraadt ping(ypdb)
457 1.8 deraadt struct _dom_binding *ypdb;
458 1.1 deraadt {
459 1.8 deraadt char *dom = ypdb->dom_domain;
460 1.17 mycroft struct rpc_msg msg;
461 1.10 deraadt char buf[1400];
462 1.10 deraadt enum clnt_stat st;
463 1.10 deraadt int outlen;
464 1.10 deraadt AUTH *rpcua;
465 1.17 mycroft XDR xdr;
466 1.10 deraadt
467 1.17 mycroft memset(&xdr, 0, sizeof xdr);
468 1.17 mycroft memset(&msg, 0, sizeof msg);
469 1.10 deraadt
470 1.10 deraadt rpcua = authunix_create_default();
471 1.17 mycroft if (rpcua == (AUTH *)NULL) {
472 1.10 deraadt /*printf("cannot get unix auth\n");*/
473 1.10 deraadt return RPC_SYSTEMERROR;
474 1.10 deraadt }
475 1.17 mycroft msg.rm_direction = CALL;
476 1.17 mycroft msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
477 1.17 mycroft msg.rm_call.cb_prog = YPPROG;
478 1.17 mycroft msg.rm_call.cb_vers = YPVERS;
479 1.17 mycroft msg.rm_call.cb_proc = YPPROC_DOMAIN_NONACK;
480 1.17 mycroft msg.rm_call.cb_cred = rpcua->ah_cred;
481 1.17 mycroft msg.rm_call.cb_verf = rpcua->ah_verf;
482 1.17 mycroft
483 1.20 cgd msg.rm_xid = ypdb->dom_xid;
484 1.17 mycroft xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
485 1.17 mycroft if (!xdr_callmsg(&xdr, &msg)) {
486 1.10 deraadt st = RPC_CANTENCODEARGS;
487 1.10 deraadt AUTH_DESTROY(rpcua);
488 1.10 deraadt return st;
489 1.10 deraadt }
490 1.17 mycroft if (!xdr_domainname(&xdr, dom)) {
491 1.10 deraadt st = RPC_CANTENCODEARGS;
492 1.10 deraadt AUTH_DESTROY(rpcua);
493 1.10 deraadt return st;
494 1.10 deraadt }
495 1.17 mycroft outlen = (int)xdr_getpos(&xdr);
496 1.17 mycroft xdr_destroy(&xdr);
497 1.17 mycroft if (outlen < 1) {
498 1.10 deraadt st = RPC_CANTENCODEARGS;
499 1.10 deraadt AUTH_DESTROY(rpcua);
500 1.10 deraadt return st;
501 1.10 deraadt }
502 1.10 deraadt AUTH_DESTROY(rpcua);
503 1.10 deraadt
504 1.10 deraadt ypdb->dom_alive = 2;
505 1.10 deraadt if (sendto(pingsock, buf, outlen, 0,
506 1.10 deraadt (struct sockaddr *)&ypdb->dom_server_addr,
507 1.10 deraadt sizeof ypdb->dom_server_addr) < 0)
508 1.10 deraadt perror("sendto");
509 1.10 deraadt return 0;
510 1.10 deraadt
511 1.10 deraadt }
512 1.10 deraadt
513 1.10 deraadt broadcast(ypdb)
514 1.10 deraadt struct _dom_binding *ypdb;
515 1.10 deraadt {
516 1.10 deraadt char *dom = ypdb->dom_domain;
517 1.17 mycroft struct rpc_msg msg;
518 1.1 deraadt char buf[1400], inbuf[8192];
519 1.9 deraadt char path[MAXPATHLEN];
520 1.1 deraadt enum clnt_stat st;
521 1.1 deraadt int outlen, i, sock, len;
522 1.17 mycroft struct sockaddr_in bindsin;
523 1.1 deraadt struct ifconf ifc;
524 1.1 deraadt struct ifreq ifreq, *ifr;
525 1.1 deraadt struct in_addr in;
526 1.1 deraadt AUTH *rpcua;
527 1.17 mycroft XDR xdr;
528 1.1 deraadt
529 1.1 deraadt rmtca.xdr_args = xdr_domainname;
530 1.1 deraadt rmtca.args_ptr = dom;
531 1.1 deraadt
532 1.17 mycroft memset(&xdr, 0, sizeof xdr);
533 1.17 mycroft memset(&msg, 0, sizeof msg);
534 1.1 deraadt
535 1.1 deraadt rpcua = authunix_create_default();
536 1.17 mycroft if (rpcua == (AUTH *)NULL) {
537 1.1 deraadt /*printf("cannot get unix auth\n");*/
538 1.1 deraadt return RPC_SYSTEMERROR;
539 1.1 deraadt }
540 1.17 mycroft msg.rm_direction = CALL;
541 1.17 mycroft msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
542 1.17 mycroft msg.rm_call.cb_prog = PMAPPROG;
543 1.17 mycroft msg.rm_call.cb_vers = PMAPVERS;
544 1.17 mycroft msg.rm_call.cb_proc = PMAPPROC_CALLIT;
545 1.17 mycroft msg.rm_call.cb_cred = rpcua->ah_cred;
546 1.17 mycroft msg.rm_call.cb_verf = rpcua->ah_verf;
547 1.17 mycroft
548 1.20 cgd msg.rm_xid = ypdb->dom_xid;
549 1.17 mycroft xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
550 1.17 mycroft if (!xdr_callmsg(&xdr, &msg)) {
551 1.1 deraadt st = RPC_CANTENCODEARGS;
552 1.1 deraadt AUTH_DESTROY(rpcua);
553 1.1 deraadt return st;
554 1.1 deraadt }
555 1.17 mycroft if (!xdr_rmtcall_args(&xdr, &rmtca)) {
556 1.1 deraadt st = RPC_CANTENCODEARGS;
557 1.1 deraadt AUTH_DESTROY(rpcua);
558 1.1 deraadt return st;
559 1.1 deraadt }
560 1.17 mycroft outlen = (int)xdr_getpos(&xdr);
561 1.17 mycroft xdr_destroy(&xdr);
562 1.17 mycroft if (outlen < 1) {
563 1.10 deraadt st = RPC_CANTENCODEARGS;
564 1.1 deraadt AUTH_DESTROY(rpcua);
565 1.1 deraadt return st;
566 1.1 deraadt }
567 1.1 deraadt AUTH_DESTROY(rpcua);
568 1.1 deraadt
569 1.17 mycroft if (ypdb->dom_lockfd != -1) {
570 1.9 deraadt close(ypdb->dom_lockfd);
571 1.9 deraadt ypdb->dom_lockfd = -1;
572 1.9 deraadt sprintf(path, "%s/%s.%d", BINDINGDIR,
573 1.10 deraadt ypdb->dom_domain, ypdb->dom_vers);
574 1.9 deraadt unlink(path);
575 1.9 deraadt }
576 1.8 deraadt
577 1.17 mycroft memset(&bindsin, 0, sizeof bindsin);
578 1.17 mycroft bindsin.sin_family = AF_INET;
579 1.17 mycroft bindsin.sin_len = sizeof(bindsin);
580 1.17 mycroft bindsin.sin_port = htons(PMAPPORT);
581 1.9 deraadt
582 1.11 ws if (ypdb->dom_alive == 2) {
583 1.11 ws /*
584 1.11 ws * This resolves the following situation:
585 1.11 ws * ypserver on other subnet was once bound,
586 1.11 ws * but rebooted and is now using a different port
587 1.11 ws */
588 1.17 mycroft bindsin.sin_addr = ypdb->dom_server_addr.sin_addr;
589 1.17 mycroft if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
590 1.17 mycroft sizeof bindsin) < 0)
591 1.11 ws perror("sendto");
592 1.11 ws }
593 1.1 deraadt /* find all networks and send the RPC packet out them all */
594 1.17 mycroft if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
595 1.1 deraadt perror("socket");
596 1.1 deraadt return -1;
597 1.1 deraadt }
598 1.9 deraadt
599 1.1 deraadt ifc.ifc_len = sizeof inbuf;
600 1.1 deraadt ifc.ifc_buf = inbuf;
601 1.17 mycroft if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
602 1.1 deraadt close(sock);
603 1.1 deraadt perror("ioctl(SIOCGIFCONF)");
604 1.1 deraadt return -1;
605 1.1 deraadt }
606 1.1 deraadt ifr = ifc.ifc_req;
607 1.1 deraadt ifreq.ifr_name[0] = '\0';
608 1.17 mycroft for (i = 0; i < ifc.ifc_len; i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
609 1.1 deraadt #if defined(BSD) && BSD >= 199103
610 1.1 deraadt len = sizeof ifr->ifr_name + ifr->ifr_addr.sa_len;
611 1.1 deraadt #else
612 1.1 deraadt len = sizeof ifc.ifc_len / sizeof(struct ifreq);
613 1.1 deraadt #endif
614 1.1 deraadt ifreq = *ifr;
615 1.17 mycroft if (ifreq.ifr_addr.sa_family != AF_INET)
616 1.1 deraadt continue;
617 1.17 mycroft if (ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0) {
618 1.1 deraadt perror("ioctl(SIOCGIFFLAGS)");
619 1.1 deraadt continue;
620 1.1 deraadt }
621 1.17 mycroft if ((ifreq.ifr_flags & IFF_UP) == 0)
622 1.1 deraadt continue;
623 1.1 deraadt
624 1.1 deraadt ifreq.ifr_flags &= (IFF_LOOPBACK | IFF_BROADCAST);
625 1.17 mycroft if (ifreq.ifr_flags == IFF_BROADCAST) {
626 1.17 mycroft if (ioctl(sock, SIOCGIFBRDADDR, &ifreq) < 0) {
627 1.1 deraadt perror("ioctl(SIOCGIFBRDADDR)");
628 1.1 deraadt continue;
629 1.1 deraadt }
630 1.17 mycroft } else if (ifreq.ifr_flags == IFF_LOOPBACK) {
631 1.17 mycroft if (ioctl(sock, SIOCGIFADDR, &ifreq) < 0) {
632 1.1 deraadt perror("ioctl(SIOCGIFADDR)");
633 1.1 deraadt continue;
634 1.1 deraadt }
635 1.1 deraadt } else
636 1.1 deraadt continue;
637 1.1 deraadt
638 1.1 deraadt in = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
639 1.17 mycroft bindsin.sin_addr = in;
640 1.17 mycroft if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
641 1.17 mycroft sizeof bindsin) < 0)
642 1.1 deraadt perror("sendto");
643 1.1 deraadt }
644 1.1 deraadt close(sock);
645 1.1 deraadt return 0;
646 1.1 deraadt }
647 1.1 deraadt
648 1.1 deraadt /*enum clnt_stat*/
649 1.1 deraadt handle_replies()
650 1.1 deraadt {
651 1.1 deraadt char buf[1400];
652 1.1 deraadt int fromlen, inlen;
653 1.20 cgd struct _dom_binding *ypdb;
654 1.1 deraadt struct sockaddr_in raddr;
655 1.1 deraadt struct rpc_msg msg;
656 1.1 deraadt XDR xdr;
657 1.1 deraadt
658 1.1 deraadt recv_again:
659 1.17 mycroft memset(&xdr, 0, sizeof(xdr));
660 1.17 mycroft memset(&msg, 0, sizeof(msg));
661 1.1 deraadt msg.acpted_rply.ar_verf = _null_auth;
662 1.1 deraadt msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr;
663 1.1 deraadt msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
664 1.1 deraadt
665 1.1 deraadt try_again:
666 1.1 deraadt fromlen = sizeof (struct sockaddr);
667 1.1 deraadt inlen = recvfrom(rpcsock, buf, sizeof buf, 0,
668 1.1 deraadt (struct sockaddr *)&raddr, &fromlen);
669 1.17 mycroft if (inlen < 0) {
670 1.17 mycroft if (errno == EINTR)
671 1.1 deraadt goto try_again;
672 1.1 deraadt return RPC_CANTRECV;
673 1.1 deraadt }
674 1.17 mycroft if (inlen < sizeof(u_int32_t))
675 1.1 deraadt goto recv_again;
676 1.1 deraadt
677 1.1 deraadt /*
678 1.1 deraadt * see if reply transaction id matches sent id.
679 1.1 deraadt * If so, decode the results.
680 1.1 deraadt */
681 1.1 deraadt xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
682 1.17 mycroft if (xdr_replymsg(&xdr, &msg)) {
683 1.17 mycroft if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
684 1.17 mycroft (msg.acpted_rply.ar_stat == SUCCESS)) {
685 1.1 deraadt raddr.sin_port = htons((u_short)rmtcr_port);
686 1.20 cgd ypdb = xid2ypdb(msg.rm_xid);
687 1.20 cgd if (ypdb != NULL)
688 1.20 cgd rpc_received(ypdb->dom_domain, &raddr, 0);
689 1.1 deraadt }
690 1.1 deraadt }
691 1.1 deraadt xdr.x_op = XDR_FREE;
692 1.1 deraadt msg.acpted_rply.ar_results.proc = xdr_void;
693 1.1 deraadt xdr_destroy(&xdr);
694 1.1 deraadt
695 1.1 deraadt return RPC_SUCCESS;
696 1.1 deraadt }
697 1.1 deraadt
698 1.10 deraadt /*enum clnt_stat*/
699 1.10 deraadt handle_ping()
700 1.10 deraadt {
701 1.10 deraadt char buf[1400];
702 1.10 deraadt int fromlen, inlen;
703 1.20 cgd struct _dom_binding *ypdb;
704 1.10 deraadt struct sockaddr_in raddr;
705 1.10 deraadt struct rpc_msg msg;
706 1.10 deraadt XDR xdr;
707 1.10 deraadt bool_t res;
708 1.10 deraadt
709 1.10 deraadt recv_again:
710 1.17 mycroft memset(&xdr, 0, sizeof(xdr));
711 1.17 mycroft memset(&msg, 0, sizeof(msg));
712 1.10 deraadt msg.acpted_rply.ar_verf = _null_auth;
713 1.10 deraadt msg.acpted_rply.ar_results.where = (caddr_t)&res;
714 1.10 deraadt msg.acpted_rply.ar_results.proc = xdr_bool;
715 1.10 deraadt
716 1.10 deraadt try_again:
717 1.10 deraadt fromlen = sizeof (struct sockaddr);
718 1.10 deraadt inlen = recvfrom(pingsock, buf, sizeof buf, 0,
719 1.10 deraadt (struct sockaddr *)&raddr, &fromlen);
720 1.17 mycroft if (inlen < 0) {
721 1.17 mycroft if (errno == EINTR)
722 1.10 deraadt goto try_again;
723 1.10 deraadt return RPC_CANTRECV;
724 1.10 deraadt }
725 1.17 mycroft if (inlen < sizeof(u_int32_t))
726 1.10 deraadt goto recv_again;
727 1.10 deraadt
728 1.10 deraadt /*
729 1.10 deraadt * see if reply transaction id matches sent id.
730 1.10 deraadt * If so, decode the results.
731 1.10 deraadt */
732 1.10 deraadt xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
733 1.17 mycroft if (xdr_replymsg(&xdr, &msg)) {
734 1.17 mycroft if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
735 1.17 mycroft (msg.acpted_rply.ar_stat == SUCCESS)) {
736 1.20 cgd ypdb = xid2ypdb(msg.rm_xid);
737 1.20 cgd if (ypdb != NULL)
738 1.20 cgd rpc_received(ypdb->dom_domain, &raddr, 0);
739 1.10 deraadt }
740 1.10 deraadt }
741 1.10 deraadt xdr.x_op = XDR_FREE;
742 1.10 deraadt msg.acpted_rply.ar_results.proc = xdr_void;
743 1.10 deraadt xdr_destroy(&xdr);
744 1.10 deraadt
745 1.10 deraadt return RPC_SUCCESS;
746 1.10 deraadt }
747 1.10 deraadt
748 1.1 deraadt /*
749 1.1 deraadt * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
750 1.1 deraadt */
751 1.1 deraadt rpc_received(dom, raddrp, force)
752 1.1 deraadt char *dom;
753 1.1 deraadt struct sockaddr_in *raddrp;
754 1.1 deraadt int force;
755 1.1 deraadt {
756 1.1 deraadt struct _dom_binding *ypdb;
757 1.6 deraadt struct iovec iov[2];
758 1.6 deraadt struct ypbind_resp ybr;
759 1.1 deraadt char path[MAXPATHLEN];
760 1.1 deraadt int fd;
761 1.14 cgd
762 1.1 deraadt /*printf("returned from %s about %s\n", inet_ntoa(raddrp->sin_addr), dom);*/
763 1.19 cgd
764 1.17 mycroft if (dom == NULL)
765 1.1 deraadt return;
766 1.1 deraadt
767 1.17 mycroft for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
768 1.17 mycroft if (!strcmp(ypdb->dom_domain, dom))
769 1.1 deraadt break;
770 1.1 deraadt
771 1.17 mycroft if (ypdb == NULL) {
772 1.17 mycroft if (force == 0)
773 1.1 deraadt return;
774 1.1 deraadt ypdb = (struct _dom_binding *)malloc(sizeof *ypdb);
775 1.17 mycroft memset(ypdb, 0, sizeof *ypdb);
776 1.1 deraadt strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain);
777 1.1 deraadt ypdb->dom_lockfd = -1;
778 1.1 deraadt ypdb->dom_pnext = ypbindlist;
779 1.1 deraadt ypbindlist = ypdb;
780 1.1 deraadt }
781 1.1 deraadt
782 1.8 deraadt /* soft update, alive */
783 1.17 mycroft if (ypdb->dom_alive == 1 && force == 0) {
784 1.17 mycroft if (!memcmp(&ypdb->dom_server_addr, raddrp,
785 1.17 mycroft sizeof ypdb->dom_server_addr)) {
786 1.8 deraadt ypdb->dom_alive = 1;
787 1.10 deraadt ypdb->dom_check_t = time(NULL) + 60; /* recheck binding in 60 sec */
788 1.8 deraadt }
789 1.1 deraadt return;
790 1.8 deraadt }
791 1.8 deraadt
792 1.17 mycroft memcpy(&ypdb->dom_server_addr, raddrp, sizeof ypdb->dom_server_addr);
793 1.10 deraadt ypdb->dom_check_t = time(NULL) + 60; /* recheck binding in 60 seconds */
794 1.1 deraadt ypdb->dom_vers = YPVERS;
795 1.1 deraadt ypdb->dom_alive = 1;
796 1.1 deraadt
797 1.17 mycroft if (ypdb->dom_lockfd != -1)
798 1.1 deraadt close(ypdb->dom_lockfd);
799 1.1 deraadt
800 1.1 deraadt sprintf(path, "%s/%s.%d", BINDINGDIR,
801 1.1 deraadt ypdb->dom_domain, ypdb->dom_vers);
802 1.1 deraadt #ifdef O_SHLOCK
803 1.17 mycroft if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) {
804 1.1 deraadt (void)mkdir(BINDINGDIR, 0755);
805 1.17 mycroft if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1)
806 1.1 deraadt return;
807 1.1 deraadt }
808 1.1 deraadt #else
809 1.17 mycroft if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) {
810 1.1 deraadt (void)mkdir(BINDINGDIR, 0755);
811 1.17 mycroft if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1)
812 1.1 deraadt return;
813 1.1 deraadt }
814 1.1 deraadt flock(fd, LOCK_SH);
815 1.3 deraadt #endif
816 1.1 deraadt
817 1.1 deraadt /*
818 1.1 deraadt * ok, if BINDINGDIR exists, and we can create the binding file,
819 1.1 deraadt * then write to it..
820 1.1 deraadt */
821 1.1 deraadt ypdb->dom_lockfd = fd;
822 1.6 deraadt
823 1.6 deraadt iov[0].iov_base = (caddr_t)&(udptransp->xp_port);
824 1.6 deraadt iov[0].iov_len = sizeof udptransp->xp_port;
825 1.6 deraadt iov[1].iov_base = (caddr_t)&ybr;
826 1.6 deraadt iov[1].iov_len = sizeof ybr;
827 1.6 deraadt
828 1.17 mycroft memset(&ybr, 0, sizeof ybr);
829 1.6 deraadt ybr.ypbind_status = YPBIND_SUCC_VAL;
830 1.6 deraadt ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr;
831 1.6 deraadt ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port;
832 1.6 deraadt
833 1.17 mycroft if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) {
834 1.1 deraadt perror("write");
835 1.1 deraadt close(ypdb->dom_lockfd);
836 1.9 deraadt unlink(path);
837 1.1 deraadt ypdb->dom_lockfd = -1;
838 1.1 deraadt return;
839 1.1 deraadt }
840 1.20 cgd }
841 1.20 cgd
842 1.20 cgd struct _dom_binding *
843 1.20 cgd xid2ypdb(xid)
844 1.20 cgd int xid;
845 1.20 cgd {
846 1.20 cgd struct _dom_binding *ypdb;
847 1.20 cgd
848 1.20 cgd for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
849 1.20 cgd if (ypdb->dom_xid == xid)
850 1.20 cgd break;
851 1.20 cgd return (ypdb);
852 1.20 cgd }
853 1.20 cgd
854 1.20 cgd int
855 1.20 cgd unique_xid(ypdb)
856 1.20 cgd struct _dom_binding *ypdb;
857 1.20 cgd {
858 1.20 cgd int tmp_xid;
859 1.20 cgd
860 1.20 cgd tmp_xid = (long)ypdb & 0xffffffff;
861 1.20 cgd while (xid2ypdb(tmp_xid) != NULL)
862 1.20 cgd tmp_xid++;
863 1.20 cgd
864 1.20 cgd return tmp_xid;
865 1.1 deraadt }
866