Bug Summary

File:src/usr.sbin/ypbind/ypbind.c
Warning:line 662, column 3
Address of stack memory associated with local variable 'dom' is still referred to by the global variable 'rmtca' upon returning to the caller. This will be a dangling reference

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ypbind.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/ypbind/obj -resource-dir /usr/local/llvm16/lib/clang/16 -D DAEMON -D HEURISTIC -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ypbind/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/ypbind/ypbind.c
1/* $OpenBSD: ypbind.c,v 1.79 2023/11/27 18:37:53 tb Exp $ */
2
3/*
4 * Copyright (c) 1992, 1993, 1996, 1997, 1998 Theo de Raadt <deraadt@openbsd.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/stat.h>
32#include <sys/uio.h>
33#include <sys/syslog.h>
34
35#include <arpa/inet.h>
36#include <net/if.h>
37#include <rpc/rpc.h>
38#include <rpc/xdr.h>
39#include <rpc/pmap_clnt.h>
40#include <rpc/pmap_prot.h>
41#include <rpc/pmap_rmt.h>
42#include <rpcsvc/yp.h>
43#include <rpcsvc/ypclnt.h>
44
45#include <ctype.h>
46#include <dirent.h>
47#include <err.h>
48#include <errno(*__errno()).h>
49#include <fcntl.h>
50#include <ifaddrs.h>
51#include <limits.h>
52#include <netdb.h>
53#include <poll.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <unistd.h>
58
59#define SERVERSDIR"/etc/yp" "/etc/yp"
60#define BINDINGDIR"/var/yp/binding" "/var/yp/binding"
61
62struct _dom_binding {
63 struct _dom_binding *dom_pnext;
64 char dom_domain[YPMAXDOMAIN64 + 1];
65 struct sockaddr_in dom_server_addr;
66 unsigned short int dom_server_port;
67 int dom_socket;
68 CLIENT *dom_client;
69 long dom_vers;
70 time_t dom_check_t;
71 time_t dom_ask_t;
72 int dom_lockfd;
73 int dom_alive;
74 u_int32_t dom_xid;
75 char dom_servlist[PATH_MAX1024];
76 FILE *dom_servlistfp;
77};
78
79void rpc_received(char *dom, struct sockaddr_in *raddrp, int force);
80void checkwork(void);
81enum clnt_stat handle_replies(void);
82enum clnt_stat handle_ping(void);
83int broadcast(struct _dom_binding *ypdb, char *, int);
84int direct(struct _dom_binding *ypdb, char *, int);
85int ping(struct _dom_binding *ypdb);
86int pings(struct _dom_binding *ypdb);
87
88char *domain;
89
90struct _dom_binding *ypbindlist;
91int check;
92
93#define YPSET_NO0 0
94#define YPSET_LOCAL1 1
95#define YPSET_ALL2 2
96int ypsetmode = YPSET_NO0;
97int insecure = 0;
98
99int rpcsock, pingsock;
100struct rmtcallargs rmtca;
101struct rmtcallres rmtcr;
102bool_tint32_t rmtcr_outval;
103u_long rmtcr_port;
104SVCXPRT *udptransp, *tcptransp;
105SVCXPRT *ludptransp, *ltcptransp;
106
107struct _dom_binding *xid2ypdb(u_int32_t xid);
108u_int32_t unique_xid(struct _dom_binding *ypdb);
109
110/*
111 * We name the local RPC functions ypbindproc_XXX_2x() instead
112 * of ypbindproc_XXX_2() because we need to pass an additional
113 * parameter. ypbindproc_setdom_2x() does a security check, and
114 * hence needs the CLIENT *
115 *
116 * We are faced with either making ypbindprog_2() do the security
117 * check before calling ypbindproc_setdom_2().. or we can simply
118 * declare sun's interface insufficient and roll our own.
119 */
120
121static void *
122ypbindproc_null_2x(SVCXPRT *transp, void *argp, CLIENT *clnt)
123{
124 static char res;
125
126 memset(&res, 0, sizeof(res));
127 return (void *)&res;
128}
129
130static struct ypbind_resp *
131ypbindproc_domain_2x(SVCXPRT *transp, domainname *argp, CLIENT *clnt)
132{
133 static struct ypbind_resp res;
134 struct _dom_binding *ypdb;
135 char path[PATH_MAX1024];
136 time_t now;
137 int count = 0;
138
139 if (strchr((char *)argp, '/'))
140 return NULL((void *)0);
141
142 memset(&res, 0, sizeof(res));
143 res.ypbind_status = YPBIND_FAIL_VAL;
144
145 for (ypdb = ypbindlist; ypdb && count < 100; ypdb = ypdb->dom_pnext)
146 count++;
147 if (count >= 100)
148 return NULL((void *)0); /* prevent DOS: sorry, you lose */
149
150 for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
151 if (!strcmp(ypdb->dom_domain, *argp))
152 break;
153
154 if (ypdb == NULL((void *)0)) {
155 ypdb = malloc(sizeof *ypdb);
156 if (ypdb == NULL((void *)0))
157 return NULL((void *)0);
158 memset(ypdb, 0, sizeof *ypdb);
159 strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain-1);
160 ypdb->dom_domain[sizeof ypdb->dom_domain-1] = '\0';
161 ypdb->dom_vers = YPVERS((u_long)2);
162 ypdb->dom_alive = 0;
163 ypdb->dom_lockfd = -1;
164 snprintf(path, sizeof path, "%s/%s.%d", BINDINGDIR"/var/yp/binding",
165 ypdb->dom_domain, (int)ypdb->dom_vers);
166 unlink(path);
167 snprintf(ypdb->dom_servlist, sizeof ypdb->dom_servlist,
168 "%s/%s", SERVERSDIR"/etc/yp", ypdb->dom_domain);
169 ypdb->dom_servlistfp = fopen(ypdb->dom_servlist, "r");
170 ypdb->dom_xid = unique_xid(ypdb);
171 ypdb->dom_pnext = ypbindlist;
172 ypbindlist = ypdb;
173 check++;
174 return NULL((void *)0);
175 }
176
177 if (ypdb->dom_alive == 0)
178 return NULL((void *)0);
179
180#ifdef HEURISTIC1
181 time(&now);
182 if (now < ypdb->dom_ask_t + 5) {
183 /*
184 * Hmm. More than 2 requests in 5 seconds have indicated
185 * that my binding is possibly incorrect.
186 * Ok, do an immediate poll of the server.
187 */
188 if (ypdb->dom_check_t >= now) {
189 /* don't flood it */
190 ypdb->dom_check_t = 0;
191 check++;
192 }
193 }
194 ypdb->dom_ask_t = now;
195#endif
196
197 res.ypbind_status = YPBIND_SUCC_VAL;
198 memmove(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
199 &ypdb->dom_server_addr.sin_addr,
200 sizeof(res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr));
201 memmove(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
202 &ypdb->dom_server_port,
203 sizeof(res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port));
204#ifdef DEBUG
205 printf("domain %s at %s/%d\n", ypdb->dom_domain,
206 inet_ntoa(ypdb->dom_server_addr.sin_addr),
207 ntohs(ypdb->dom_server_addr.sin_port)(__uint16_t)(__builtin_constant_p(ypdb->dom_server_addr.sin_port
) ? (__uint16_t)(((__uint16_t)(ypdb->dom_server_addr.sin_port
) & 0xffU) << 8 | ((__uint16_t)(ypdb->dom_server_addr
.sin_port) & 0xff00U) >> 8) : __swap16md(ypdb->dom_server_addr
.sin_port))
);
208#endif
209 return &res;
210}
211
212static bool_tint32_t *
213ypbindproc_setdom_2x(SVCXPRT *transp, struct ypbind_setdom *argp, CLIENT *clnt)
214{
215 struct sockaddr_in *fromsin, bindsin;
216 static bool_tint32_t res = 1;
217
218 fromsin = svc_getcaller(transp)(&(transp)->xp_raddr);
219
220 switch (ypsetmode) {
221 case YPSET_LOCAL1:
222 if (transp != ludptransp && transp != ltcptransp) {
223 syslog(LOG_WARNING4, "attempted spoof of ypsetme");
224 svcerr_weakauth(transp);
225 return NULL((void *)0);
226 }
227 if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
) {
228 svcerr_weakauth(transp);
229 return NULL((void *)0);
230 }
231 break;
232 case YPSET_ALL2:
233 break;
234 case YPSET_NO0:
235 default:
236 svcerr_weakauth(transp);
237 return NULL((void *)0);
238 }
239
240 if (ntohs(fromsin->sin_port)(__uint16_t)(__builtin_constant_p(fromsin->sin_port) ? (__uint16_t
)(((__uint16_t)(fromsin->sin_port) & 0xffU) << 8
| ((__uint16_t)(fromsin->sin_port) & 0xff00U) >>
8) : __swap16md(fromsin->sin_port))
>= IPPORT_RESERVED1024) {
241 svcerr_weakauth(transp);
242 return NULL((void *)0);
243 }
244
245 if (argp->ypsetdom_vers != YPVERS((u_long)2)) {
246 svcerr_noprog(transp);
247 return NULL((void *)0);
248 }
249
250 memset(&bindsin, 0, sizeof bindsin);
251 bindsin.sin_family = AF_INET2;
252 bindsin.sin_len = sizeof(bindsin);
253 memcpy(&bindsin.sin_addr, &argp->ypsetdom_binding.ypbind_binding_addr,
254 sizeof(argp->ypsetdom_binding.ypbind_binding_addr));
255 memcpy(&bindsin.sin_port, &argp->ypsetdom_binding.ypbind_binding_port,
256 sizeof(argp->ypsetdom_binding.ypbind_binding_port));
257 rpc_received(argp->ypsetdom_domain, &bindsin, 1);
258
259 return &res;
260}
261
262static void
263ypbindprog_2(struct svc_req *rqstp, SVCXPRT *transp)
264{
265 union argument {
266 domainname ypbindproc_domain_2_arg;
267 struct ypbind_setdom ypbindproc_setdom_2_arg;
268 } argument;
269 struct authunix_parms *creds;
270 char *result;
271 xdrproc_t xdr_argument, xdr_result;
272 char *(*local)(SVCXPRT *, union argument *, struct svc_req *);
273
274 switch (rqstp->rq_proc) {
275 case YPBINDPROC_NULL((u_long)0):
276 xdr_argument = xdr_void;
277 xdr_result = xdr_void;
278 local = (char *(*)(SVCXPRT *, union argument *, struct svc_req *))
279 ypbindproc_null_2x;
280 break;
281
282 case YPBINDPROC_DOMAIN((u_long)1):
283 xdr_argument = xdr_domainname;
284 xdr_result = xdr_ypbind_resp;
285 local = (char *(*)(SVCXPRT *, union argument *, struct svc_req *))
286 ypbindproc_domain_2x;
287 break;
288
289 case YPBINDPROC_SETDOM((u_long)2):
290 switch (rqstp->rq_cred.oa_flavor) {
291 case AUTH_UNIX1:
292 creds = (struct authunix_parms *)rqstp->rq_clntcred;
293 if (creds->aup_uid != 0) {
294 svcerr_auth(transp, AUTH_BADCRED);
295 return;
296 }
297 break;
298 default:
299 svcerr_auth(transp, AUTH_TOOWEAK);
300 return;
301 }
302
303 xdr_argument = xdr_ypbind_setdom;
304 xdr_result = xdr_void;
305 local = (char *(*)(SVCXPRT *, union argument *, struct svc_req *))
306 ypbindproc_setdom_2x;
307 break;
308
309 default:
310 svcerr_noproc(transp);
311 return;
312 }
313 memset(&argument, 0, sizeof(argument));
314 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)(*(transp)->xp_ops->xp_getargs)((transp), (xdr_argument
), ((caddr_t)&argument))
) {
315 svcerr_decode(transp);
316 return;
317 }
318 result = (*local)(transp, &argument, rqstp);
319 if (result != NULL((void *)0) && !svc_sendreply(transp, xdr_result, result)) {
320 svcerr_systemerr(transp);
321 }
322 return;
323}
324
325static void
326usage(void)
327{
328 fprintf(stderr(&__sF[2]), "usage: ypbind [-insecure] [-ypset] [-ypsetme]\n");
329 exit(1);
330}
331
332int
333main(int argc, char *argv[])
334{
335 char path[PATH_MAX1024];
336 struct sockaddr_in sin;
337 struct pollfd *pfd = NULL((void *)0);
338 int width = 0, nready, lsock;
339 socklen_t len;
340 int evil = 0, one = 1;
341 DIR *dirp;
342 struct dirent *dent;
343
344 if (yp_get_default_domain(&domain) != 0 || domain[0] == '\0') {
1
Assuming the condition is false
2
Assuming the condition is false
3
Taking false branch
345 fprintf(stderr(&__sF[2]), "domainname not set. Aborting.\n");
346 exit(1);
347 }
348
349 while (--argc) {
4
Loop condition is false. Execution continues on line 362
350 ++argv;
351 if (!strcmp("-insecure", *argv))
352 insecure = 1;
353 else if (!strcmp("-ypset", *argv))
354 ypsetmode = YPSET_ALL2;
355 else if (!strcmp("-ypsetme", *argv))
356 ypsetmode = YPSET_LOCAL1;
357 else
358 usage();
359 }
360
361 /* blow away everything in BINDINGDIR */
362 dirp = opendir(BINDINGDIR"/var/yp/binding");
363 if (dirp) {
5
Assuming 'dirp' is null
6
Taking false branch
364 while ((dent = readdir(dirp))) {
365 if (!strcmp(dent->d_name, ".") ||
366 !strcmp(dent->d_name, ".."))
367 continue;
368 (void)unlinkat(dirfd(dirp), dent->d_name, 0);
369 }
370 closedir(dirp);
371 } else {
372 (void)mkdir(BINDINGDIR"/var/yp/binding", 0755);
373 }
374
375 (void)pmap_unset(YPBINDPROG((u_long)100007), YPBINDVERS((u_long)2));
376
377 udptransp = svcudp_create(RPC_ANYSOCK-1);
378 if (udptransp == NULL((void *)0)) {
7
Assuming 'udptransp' is not equal to NULL
8
Taking false branch
379 fprintf(stderr(&__sF[2]), "cannot create udp service.\n");
380 exit(1);
381 }
382 if (!svc_register(udptransp, YPBINDPROG((u_long)100007), YPBINDVERS((u_long)2), ypbindprog_2,
9
Assuming the condition is false
10
Taking false branch
383 IPPROTO_UDP17)) {
384 fprintf(stderr(&__sF[2]),
385 "unable to register (YPBINDPROG, YPBINDVERS, udp).\n");
386 exit(1);
387 }
388
389 tcptransp = svctcp_create(RPC_ANYSOCK-1, 0, 0);
390 if (tcptransp == NULL((void *)0)) {
11
Assuming 'tcptransp' is not equal to NULL
12
Taking false branch
391 fprintf(stderr(&__sF[2]), "cannot create tcp service.\n");
392 exit(1);
393 }
394 if (!svc_register(tcptransp, YPBINDPROG((u_long)100007), YPBINDVERS((u_long)2), ypbindprog_2,
13
Assuming the condition is false
14
Taking false branch
395 IPPROTO_TCP6)) {
396 fprintf(stderr(&__sF[2]),
397 "unable to register (YPBINDPROG, YPBINDVERS, tcp).\n");
398 exit(1);
399 }
400
401 if (ypsetmode
14.1
'ypsetmode' is not equal to YPSET_LOCAL
== YPSET_LOCAL1) {
15
Taking false branch
402 /* build UDP local port */
403 if ((lsock = socket(AF_INET2, SOCK_DGRAM2, IPPROTO_UDP17)) == -1) {
404 syslog(LOG_ERR3, "cannot create local udp socket: %m");
405 exit(1);
406 }
407 (void)setsockopt(lsock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, &one,
408 (socklen_t)sizeof one);
409 len = sizeof(sin);
410 if (getsockname(udptransp->xp_sock, (struct sockaddr *)&sin,
411 &len) == -1) {
412 syslog(LOG_ERR3, "cannot getsockname local udp: %m");
413 exit(1);
414 }
415 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
;
416 sin.sin_port = htons(udptransp->xp_port)(__uint16_t)(__builtin_constant_p(udptransp->xp_port) ? (__uint16_t
)(((__uint16_t)(udptransp->xp_port) & 0xffU) << 8
| ((__uint16_t)(udptransp->xp_port) & 0xff00U) >>
8) : __swap16md(udptransp->xp_port))
;
417 if (bind(lsock, (struct sockaddr *)&sin, len) != 0) {
418 syslog(LOG_ERR3, "cannot bind local udp: %m");
419 exit(1);
420 }
421 if ((ludptransp = svcudp_create(lsock)) == NULL((void *)0)) {
422 fprintf(stderr(&__sF[2]), "cannot create udp service.\n");
423 exit(1);
424 }
425
426 /* build TCP local port */
427 if ((lsock = socket(AF_INET2, SOCK_STREAM1, IPPROTO_TCP6)) == -1) {
428 syslog(LOG_ERR3, "cannot create udp socket: %m");
429 exit(1);
430 }
431 (void)setsockopt(lsock, SOL_SOCKET0xffff, SO_REUSEADDR0x0004, &one,
432 (socklen_t)sizeof one);
433 len = sizeof(sin);
434 if (getsockname(tcptransp->xp_sock, (struct sockaddr *)&sin,
435 &len) == -1) {
436 syslog(LOG_ERR3, "cannot getsockname udp: %m");
437 exit(1);
438 }
439 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
;
440 sin.sin_port = htons(tcptransp->xp_port)(__uint16_t)(__builtin_constant_p(tcptransp->xp_port) ? (__uint16_t
)(((__uint16_t)(tcptransp->xp_port) & 0xffU) << 8
| ((__uint16_t)(tcptransp->xp_port) & 0xff00U) >>
8) : __swap16md(tcptransp->xp_port))
;
441 if (bind(lsock, (struct sockaddr *)&sin, len) == -1) {
442 syslog(LOG_ERR3, "cannot bind local tcp: %m");
443 exit(1);
444 }
445 if ((ltcptransp = svctcp_create(lsock, 0, 0)) == NULL((void *)0)) {
446 fprintf(stderr(&__sF[2]), "cannot create tcp service.\n");
447 exit(1);
448 }
449 }
450
451 if ((rpcsock = socket(AF_INET2, SOCK_DGRAM2 | SOCK_NONBLOCK0x4000, 0)) == -1) {
16
Assuming the condition is false
17
Taking false branch
452 perror("socket");
453 return -1;
454 }
455 memset(&sin, 0, sizeof sin);
456 sin.sin_family = AF_INET2;
457 sin.sin_addr.s_addr = htonl(INADDR_ANY)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x00000000))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x00000000))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x00000000))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x00000000))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x00000000
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x00000000))))
;
18
'?' condition is true
458 sin.sin_port = 0;
459 bindresvport(rpcsock, &sin);
460
461 if ((pingsock = socket(AF_INET2, SOCK_DGRAM2 | SOCK_NONBLOCK0x4000, 0)) == -1) {
19
Assuming the condition is false
20
Taking false branch
462 perror("socket");
463 return -1;
464 }
465 memset(&sin, 0, sizeof sin);
466 sin.sin_family = AF_INET2;
467 sin.sin_addr.s_addr = htonl(INADDR_ANY)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x00000000))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x00000000))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x00000000))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x00000000))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x00000000
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x00000000))))
;
21
'?' condition is true
468 sin.sin_port = 0;
469 bindresvport(pingsock, &sin);
470
471 setsockopt(rpcsock, SOL_SOCKET0xffff, SO_BROADCAST0x0020, &one,
472 (socklen_t)sizeof(one));
473 rmtca.prog = YPPROG((u_long)100004);
474 rmtca.vers = YPVERS((u_long)2);
475 rmtca.proc = YPPROC_DOMAIN_NONACK((u_long)2);
476 rmtca.xdr_args = NULL((void *)0); /* set at call time */
477 rmtca.args_ptr = NULL((void *)0); /* set at call time */
478 rmtcr.port_ptr = &rmtcr_port;
479 rmtcr.xdr_results = xdr_bool;
480 rmtcr.results_ptr = (caddr_t)&rmtcr_outval;
481
482 if (strchr(domain, '/'))
22
Assuming the condition is false
23
Taking false branch
483 errx(1, "bad domainname %s", domain);
484
485 /* build initial domain binding, make it "unsuccessful" */
486 ypbindlist = malloc(sizeof *ypbindlist);
487 if (ypbindlist == NULL((void *)0))
24
Assuming 'ypbindlist' is not equal to NULL
25
Taking false branch
488 errx(1, "no memory");
489 memset(ypbindlist, 0, sizeof *ypbindlist);
490 strncpy(ypbindlist->dom_domain, domain, sizeof ypbindlist->dom_domain-1);
491 ypbindlist->dom_domain[sizeof (ypbindlist->dom_domain)-1] = '\0';
492 ypbindlist->dom_vers = YPVERS((u_long)2);
493 snprintf(ypbindlist->dom_servlist, sizeof ypbindlist->dom_servlist,
494 "%s/%s", SERVERSDIR"/etc/yp", ypbindlist->dom_domain);
495 ypbindlist->dom_servlistfp = fopen(ypbindlist->dom_servlist, "r");
496 ypbindlist->dom_alive = 0;
497 ypbindlist->dom_lockfd = -1;
498 ypbindlist->dom_xid = unique_xid(ypbindlist);
499 snprintf(path, sizeof path, "%s/%s.%d", BINDINGDIR"/var/yp/binding",
500 ypbindlist->dom_domain, (int)ypbindlist->dom_vers);
501 (void)unlink(path);
502
503 checkwork();
26
Calling 'checkwork'
504
505 while (1) {
506 if (pfd == NULL((void *)0) || width != svc_max_pollfd + 2) {
507 width = svc_max_pollfd + 2;
508 pfd = reallocarray(pfd, width, sizeof *pfd);
509 if (pfd == NULL((void *)0))
510 err(1, NULL((void *)0));
511 }
512
513 pfd[0].fd = rpcsock;
514 pfd[0].events = POLLIN0x0001;
515 pfd[1].fd = pingsock;
516 pfd[1].events = POLLIN0x0001;
517 memcpy(pfd + 2, svc_pollfd, sizeof(*pfd) * svc_max_pollfd);
518
519 nready = poll(pfd, width, 1000);
520 switch (nready) {
521 case 0:
522 checkwork();
523 break;
524 case -1:
525 if (errno(*__errno()) != EINTR4)
526 perror("poll");
527 break;
528 default:
529 /* No need to check for POLLHUP on UDP sockets. */
530 if (pfd[0].revents & POLLIN0x0001) {
531 handle_replies();
532 nready--;
533 }
534 if (pfd[1].revents & POLLIN0x0001) {
535 handle_ping();
536 nready--;
537 }
538 svc_getreq_poll(pfd + 2, nready);
539 if (check)
540 checkwork();
541 break;
542 }
543
544#ifdef DAEMON1
545 if (!evil && ypbindlist->dom_alive) {
546 evil = 1;
547 daemon(0, 0);
548 }
549#endif
550 }
551}
552
553/*
554 * State transition is done like this:
555 *
556 * STATE EVENT ACTION NEWSTATE TIMEOUT
557 * no binding timeout broadcast no binding 5 sec
558 * no binding answer -- binding 60 sec
559 * binding timeout ping server checking 5 sec
560 * checking timeout ping server + broadcast checking 5 sec
561 * checking answer -- binding 60 sec
562 */
563void
564checkwork(void)
565{
566 struct _dom_binding *ypdb;
567 time_t t;
568
569 time(&t);
570 for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) {
27
Loop condition is true. Entering loop body
571 if (ypdb->dom_check_t < t) {
28
Assuming 't' is > field 'dom_check_t'
29
Taking true branch
572 if (ypdb->dom_alive == 1)
30
Assuming field 'dom_alive' is not equal to 1
31
Taking false branch
573 ping(ypdb);
574 else
575 pings(ypdb);
32
Calling 'pings'
576 time(&t);
577 ypdb->dom_check_t = t + 5;
578 }
579 }
580 check = 0;
581}
582
583int
584ping(struct _dom_binding *ypdb)
585{
586 domainname dom = ypdb->dom_domain;
587 struct rpc_msg msg;
588 char buf[1400];
589 enum clnt_stat st;
590 int outlen;
591 AUTH *rpcua;
592 XDR xdr;
593
594 memset(&xdr, 0, sizeof xdr);
595 memset(&msg, 0, sizeof msg);
596
597 rpcua = authunix_create_default();
598 if (rpcua == (AUTH *)NULL((void *)0)) {
599 /*printf("cannot get unix auth\n");*/
600 return RPC_SYSTEMERROR;
601 }
602 msg.rm_direction = CALL;
603 msg.rm_callru.RM_cmb.cb_rpcvers = RPC_MSG_VERSION((unsigned long) 2);
604 msg.rm_callru.RM_cmb.cb_prog = YPPROG((u_long)100004);
605 msg.rm_callru.RM_cmb.cb_vers = YPVERS((u_long)2);
606 msg.rm_callru.RM_cmb.cb_proc = YPPROC_DOMAIN_NONACK((u_long)2);
607 msg.rm_callru.RM_cmb.cb_cred = rpcua->ah_cred;
608 msg.rm_callru.RM_cmb.cb_verf = rpcua->ah_verf;
609
610 msg.rm_xid = ypdb->dom_xid;
611 xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
612 if (!xdr_callmsg(&xdr, &msg)) {
613 st = RPC_CANTENCODEARGS;
614 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
615 return st;
616 }
617 if (!xdr_domainname(&xdr, &dom)) {
618 st = RPC_CANTENCODEARGS;
619 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
620 return st;
621 }
622 outlen = (int)xdr_getpos(&xdr)(*(&xdr)->x_ops->x_getpostn)(&xdr);
623 xdr_destroy(&xdr)if ((&xdr)->x_ops->x_destroy) (*(&xdr)->x_ops
->x_destroy)(&xdr)
;
624 if (outlen < 1) {
625 st = RPC_CANTENCODEARGS;
626 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
627 return st;
628 }
629 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
630
631 ypdb->dom_alive = 2;
632 if (sendto(pingsock, buf, outlen, 0,
633 (struct sockaddr *)&ypdb->dom_server_addr,
634 (socklen_t)sizeof ypdb->dom_server_addr) == -1)
635 perror("sendto");
636 return 0;
637
638}
639
640int
641pings(struct _dom_binding *ypdb)
642{
643 domainname dom = ypdb->dom_domain;
644 struct rpc_msg msg;
645 struct sockaddr_in bindsin;
646 char buf[1400];
647 char path[PATH_MAX1024];
648 enum clnt_stat st;
649 int outlen;
650 AUTH *rpcua;
651 XDR xdr;
652
653 rmtca.xdr_args = xdr_domainname;
654 rmtca.args_ptr = (char *)&dom;
655
656 memset(&xdr, 0, sizeof xdr);
657 memset(&msg, 0, sizeof msg);
658
659 rpcua = authunix_create_default();
660 if (rpcua == (AUTH *)NULL((void *)0)) {
33
Assuming 'rpcua' is equal to null
34
Taking true branch
661 /*printf("cannot get unix auth\n");*/
662 return RPC_SYSTEMERROR;
35
Address of stack memory associated with local variable 'dom' is still referred to by the global variable 'rmtca' upon returning to the caller. This will be a dangling reference
663 }
664 msg.rm_direction = CALL;
665 msg.rm_callru.RM_cmb.cb_rpcvers = RPC_MSG_VERSION((unsigned long) 2);
666 msg.rm_callru.RM_cmb.cb_prog = PMAPPROG((unsigned long)100000);
667 msg.rm_callru.RM_cmb.cb_vers = PMAPVERS((unsigned long)2);
668 msg.rm_callru.RM_cmb.cb_proc = PMAPPROC_CALLIT((unsigned long)5);
669 msg.rm_callru.RM_cmb.cb_cred = rpcua->ah_cred;
670 msg.rm_callru.RM_cmb.cb_verf = rpcua->ah_verf;
671
672 msg.rm_xid = ypdb->dom_xid;
673 xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE);
674 if (!xdr_callmsg(&xdr, &msg)) {
675 st = RPC_CANTENCODEARGS;
676 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
677 return st;
678 }
679 if (!xdr_rmtcall_args(&xdr, &rmtca)) {
680 st = RPC_CANTENCODEARGS;
681 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
682 return st;
683 }
684 outlen = (int)xdr_getpos(&xdr)(*(&xdr)->x_ops->x_getpostn)(&xdr);
685 xdr_destroy(&xdr)if ((&xdr)->x_ops->x_destroy) (*(&xdr)->x_ops
->x_destroy)(&xdr)
;
686 if (outlen < 1) {
687 st = RPC_CANTENCODEARGS;
688 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
689 return st;
690 }
691 AUTH_DESTROY(rpcua)((*((rpcua)->ah_ops->ah_destroy))(rpcua));
692
693 if (ypdb->dom_lockfd != -1) {
694 close(ypdb->dom_lockfd);
695 ypdb->dom_lockfd = -1;
696 snprintf(path, sizeof path, "%s/%s.%d", BINDINGDIR"/var/yp/binding",
697 ypdb->dom_domain, (int)ypdb->dom_vers);
698 unlink(path);
699 }
700
701 if (ypdb->dom_alive == 2) {
702 /*
703 * This resolves the following situation:
704 * ypserver on other subnet was once bound,
705 * but rebooted and is now using a different port
706 */
707 memset(&bindsin, 0, sizeof bindsin);
708 bindsin.sin_family = AF_INET2;
709 bindsin.sin_len = sizeof(bindsin);
710 bindsin.sin_port = htons(PMAPPORT)(__uint16_t)(__builtin_constant_p(((unsigned short)111)) ? (__uint16_t
)(((__uint16_t)(((unsigned short)111)) & 0xffU) << 8
| ((__uint16_t)(((unsigned short)111)) & 0xff00U) >>
8) : __swap16md(((unsigned short)111)))
;
711 bindsin.sin_addr = ypdb->dom_server_addr.sin_addr;
712 if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
713 (socklen_t)sizeof bindsin) == -1)
714 perror("sendto");
715 }
716 if (ypdb->dom_servlistfp)
717 return direct(ypdb, buf, outlen);
718 return broadcast(ypdb, buf, outlen);
719}
720
721int
722broadcast(struct _dom_binding *ypdb, char *buf, int outlen)
723{
724 struct ifaddrs *ifap, *ifa;
725 struct sockaddr_in bindsin;
726 struct in_addr in;
727
728 memset(&bindsin, 0, sizeof bindsin);
729 bindsin.sin_family = AF_INET2;
730 bindsin.sin_len = sizeof(bindsin);
731 bindsin.sin_port = htons(PMAPPORT)(__uint16_t)(__builtin_constant_p(((unsigned short)111)) ? (__uint16_t
)(((__uint16_t)(((unsigned short)111)) & 0xffU) << 8
| ((__uint16_t)(((unsigned short)111)) & 0xff00U) >>
8) : __swap16md(((unsigned short)111)))
;
732
733 if (getifaddrs(&ifap) != 0) {
734 perror("getifaddrs");
735 return -1;
736 }
737 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
738 if (ifa->ifa_addr == NULL((void *)0) ||
739 ifa->ifa_addr->sa_family != AF_INET2)
740 continue;
741 if ((ifa->ifa_flags & IFF_UP0x1) == 0)
742 continue;
743
744 switch (ifa->ifa_flags & (IFF_LOOPBACK0x8 | IFF_BROADCAST0x2)) {
745 case IFF_BROADCAST0x2:
746 if (!ifa->ifa_broadaddrifa_dstaddr)
747 continue;
748 if (ifa->ifa_broadaddrifa_dstaddr->sa_family != AF_INET2)
749 continue;
750 in = ((struct sockaddr_in *)ifa->ifa_broadaddrifa_dstaddr)->sin_addr;
751 break;
752 case IFF_LOOPBACK0x8:
753 in = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
754 break;
755 default:
756 continue;
757 }
758
759 bindsin.sin_addr = in;
760 if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin,
761 (socklen_t)bindsin.sin_len) == -1)
762 perror("sendto");
763 }
764 freeifaddrs(ifap);
765 return 0;
766}
767
768int
769direct(struct _dom_binding *ypdb, char *buf, int outlen)
770{
771 char line[1024], *p;
772 struct hostent *hp;
773 struct sockaddr_in bindsin;
774 int i, c;
775 struct stat fst, st;
776
777 if (fstat(fileno(ypdb->dom_servlistfp)(!__isthreaded ? ((ypdb->dom_servlistfp)->_file) : (fileno
)(ypdb->dom_servlistfp))
, &fst) != -1 &&
778 stat(ypdb->dom_servlist, &st) != -1 &&
779 (st.st_dev != fst.st_dev || st.st_ino != fst.st_ino)) {
780 FILE *fp;
781
782 fp = fopen(ypdb->dom_servlist, "r");
783 if (fp) {
784 fclose(ypdb->dom_servlistfp);
785 ypdb->dom_servlistfp = fp;
786 }
787 }
788 (void) rewind(ypdb->dom_servlistfp);
789
790 memset(&bindsin, 0, sizeof bindsin);
791 bindsin.sin_family = AF_INET2;
792 bindsin.sin_len = sizeof(bindsin);
793 bindsin.sin_port = htons(PMAPPORT)(__uint16_t)(__builtin_constant_p(((unsigned short)111)) ? (__uint16_t
)(((__uint16_t)(((unsigned short)111)) & 0xffU) << 8
| ((__uint16_t)(((unsigned short)111)) & 0xff00U) >>
8) : __swap16md(((unsigned short)111)))
;
794
795 while (fgets(line, sizeof(line), ypdb->dom_servlistfp) != NULL((void *)0)) {
796 /* skip lines that are too big */
797 p = strchr(line, '\n');
798 if (p == NULL((void *)0)) {
799 while ((c = getc(ypdb->dom_servlistfp)(!__isthreaded ? (--(ypdb->dom_servlistfp)->_r < 0 ?
__srget(ypdb->dom_servlistfp) : (int)(*(ypdb->dom_servlistfp
)->_p++)) : (getc)(ypdb->dom_servlistfp))
) != '\n' && c != EOF(-1))
800 ;
801 continue;
802 }
803 *p = '\0';
804 p = line;
805 while (isspace((unsigned char)*p))
806 p++;
807 if (*p == '#')
808 continue;
809 hp = gethostbyname(p);
810 if (!hp)
811 continue;
812 /* step through all addresses in case first is unavailable */
813 for (i = 0; hp->h_addr_list[i]; i++) {
814 memmove(&bindsin.sin_addr, hp->h_addr_list[0],
815 hp->h_length);
816 if (sendto(rpcsock, buf, outlen, 0,
817 (struct sockaddr *)&bindsin,
818 (socklen_t)sizeof bindsin) == -1) {
819 perror("sendto");
820 continue;
821 }
822 }
823 }
824 return 0;
825}
826
827enum clnt_stat
828handle_replies(void)
829{
830 char buf[1400];
831 int inlen;
832 socklen_t fromlen;
833 struct _dom_binding *ypdb;
834 struct sockaddr_in raddr;
835 struct rpc_msg msg;
836 XDR xdr;
837
838recv_again:
839 memset(&xdr, 0, sizeof(xdr));
840 memset(&msg, 0, sizeof(msg));
841 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_verf = _null_auth;
842 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.where = (caddr_t)&rmtcr;
843 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.proc = xdr_rmtcallres;
844
845try_again:
846 fromlen = sizeof (struct sockaddr);
847 inlen = recvfrom(rpcsock, buf, sizeof buf, 0,
848 (struct sockaddr *)&raddr, &fromlen);
849 if (inlen == -1) {
850 if (errno(*__errno()) == EINTR4)
851 goto try_again;
852 return RPC_CANTRECV;
853 }
854 if (inlen < sizeof(u_int32_t))
855 goto recv_again;
856
857 /*
858 * see if reply transaction id matches sent id.
859 * If so, decode the results.
860 */
861 xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
862 if (xdr_replymsg(&xdr, &msg)) {
863 if ((msg.rm_replyru.RM_rmb.rp_stat == MSG_ACCEPTED) &&
864 (msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_stat == SUCCESS)) {
865 raddr.sin_port = htons((u_short)rmtcr_port)(__uint16_t)(__builtin_constant_p((u_short)rmtcr_port) ? (__uint16_t
)(((__uint16_t)((u_short)rmtcr_port) & 0xffU) << 8 |
((__uint16_t)((u_short)rmtcr_port) & 0xff00U) >> 8
) : __swap16md((u_short)rmtcr_port))
;
866 ypdb = xid2ypdb(msg.rm_xid);
867 if (ypdb)
868 rpc_received(ypdb->dom_domain, &raddr, 0);
869 }
870 }
871 xdr.x_op = XDR_FREE;
872 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.proc = xdr_void;
873 xdr_destroy(&xdr)if ((&xdr)->x_ops->x_destroy) (*(&xdr)->x_ops
->x_destroy)(&xdr)
;
874
875 return RPC_SUCCESS;
876}
877
878enum clnt_stat
879handle_ping(void)
880{
881 char buf[1400];
882 int inlen;
883 socklen_t fromlen;
884 struct _dom_binding *ypdb;
885 struct sockaddr_in raddr;
886 struct rpc_msg msg;
887 XDR xdr;
888 bool_tint32_t res;
889
890recv_again:
891 memset(&xdr, 0, sizeof(xdr));
892 memset(&msg, 0, sizeof(msg));
893 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_verf = _null_auth;
894 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.where = (caddr_t)&res;
895 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.proc = xdr_bool;
896
897try_again:
898 fromlen = sizeof (struct sockaddr);
899 inlen = recvfrom(pingsock, buf, sizeof buf, 0,
900 (struct sockaddr *)&raddr, &fromlen);
901 if (inlen == -1) {
902 if (errno(*__errno()) == EINTR4)
903 goto try_again;
904 return RPC_CANTRECV;
905 }
906 if (inlen < sizeof(u_int32_t))
907 goto recv_again;
908
909 /*
910 * see if reply transaction id matches sent id.
911 * If so, decode the results.
912 */
913 xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);
914 if (xdr_replymsg(&xdr, &msg)) {
915 if ((msg.rm_replyru.RM_rmb.rp_stat == MSG_ACCEPTED) &&
916 (msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_stat == SUCCESS)) {
917 ypdb = xid2ypdb(msg.rm_xid);
918 if (ypdb)
919 rpc_received(ypdb->dom_domain, &raddr, 0);
920 }
921 }
922 xdr.x_op = XDR_FREE;
923 msg.acpted_rplyru.RM_rmb.ru.RP_ar.ar_resultsru.AR_results.proc = xdr_void;
924 xdr_destroy(&xdr)if ((&xdr)->x_ops->x_destroy) (*(&xdr)->x_ops
->x_destroy)(&xdr)
;
925
926 return RPC_SUCCESS;
927}
928
929/*
930 * We prefer loopback connections.
931 */
932void
933rpc_received(char *dom, struct sockaddr_in *raddrp, int force)
934{
935 struct _dom_binding *ypdb;
936 struct iovec iov[3];
937 struct ypbind_resp ybr;
938 char path[PATH_MAX1024];
939 u_short ypserv_tcp, ypserv_udp;
940 int fd;
941
942 if (strchr(dom, '/'))
943 return;
944
945#ifdef DEBUG
946 printf("returned from %s about %s\n", inet_ntoa(raddrp->sin_addr), dom);
947#endif
948
949 if (dom == NULL((void *)0))
950 return;
951
952 for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
953 if (!strcmp(ypdb->dom_domain, dom))
954 break;
955
956 if (ypdb == NULL((void *)0)) {
957 if (force == 0)
958 return;
959 ypdb = malloc(sizeof *ypdb);
960 if (ypdb == NULL((void *)0))
961 return;
962 memset(ypdb, 0, sizeof *ypdb);
963 strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain-1);
964 ypdb->dom_domain[sizeof (ypdb->dom_domain)-1] = '\0';
965 ypdb->dom_lockfd = -1;
966 ypdb->dom_xid = unique_xid(ypdb);
967 ypdb->dom_pnext = ypbindlist;
968 ypbindlist = ypdb;
969 }
970
971 /* we do not support sunos 3.0 insecure servers */
972 if (insecure == 0 && ntohs(raddrp->sin_port)(__uint16_t)(__builtin_constant_p(raddrp->sin_port) ? (__uint16_t
)(((__uint16_t)(raddrp->sin_port) & 0xffU) << 8 |
((__uint16_t)(raddrp->sin_port) & 0xff00U) >> 8
) : __swap16md(raddrp->sin_port))
>= IPPORT_RESERVED1024)
973 return;
974
975 /* soft update, alive */
976 if (ypdb->dom_alive == 1 && force == 0) {
977 if (!memcmp(&ypdb->dom_server_addr, raddrp,
978 sizeof ypdb->dom_server_addr)) {
979 ypdb->dom_alive = 1;
980 /* recheck binding in 60 sec */
981 ypdb->dom_check_t = time(NULL((void *)0)) + 60;
982 }
983 if (raddrp->sin_addr.s_addr == htonl(INADDR_LOOPBACK)(__uint32_t)(__builtin_constant_p(((u_int32_t)(0x7f000001))) ?
(__uint32_t)(((__uint32_t)(((u_int32_t)(0x7f000001))) & 0xff
) << 24 | ((__uint32_t)(((u_int32_t)(0x7f000001))) &
0xff00) << 8 | ((__uint32_t)(((u_int32_t)(0x7f000001))
) & 0xff0000) >> 8 | ((__uint32_t)(((u_int32_t)(0x7f000001
))) & 0xff000000) >> 24) : __swap32md(((u_int32_t)(
0x7f000001))))
) {
984 /*
985 * we are alive and already have a binding, but
986 * after a broadcast we prefer the localhost
987 */
988 memcpy(&ypdb->dom_server_addr, raddrp,
989 sizeof ypdb->dom_server_addr);
990 }
991 return;
992 }
993
994 /* synchronously ask for the matching ypserv TCP port number */
995 ypserv_udp = raddrp->sin_port;
996 ypserv_tcp = pmap_getport(raddrp, YPPROG((u_long)100004),
997 YPVERS((u_long)2), IPPROTO_TCP6);
998 if (ypserv_tcp == 0) {
999 clnt_pcreateerror("pmap_getport");
1000 return;
1001 }
1002 if (ypserv_tcp >= IPPORT_RESERVED1024 || ypserv_tcp == 20)
1003 return;
1004 ypserv_tcp = htons(ypserv_tcp)(__uint16_t)(__builtin_constant_p(ypserv_tcp) ? (__uint16_t)(
((__uint16_t)(ypserv_tcp) & 0xffU) << 8 | ((__uint16_t
)(ypserv_tcp) & 0xff00U) >> 8) : __swap16md(ypserv_tcp
))
;
1005
1006 memcpy(&ypdb->dom_server_addr, raddrp, sizeof ypdb->dom_server_addr);
1007 /* recheck binding in 60 seconds */
1008 ypdb->dom_check_t = time(NULL((void *)0)) + 60;
1009 ypdb->dom_vers = YPVERS((u_long)2);
1010 ypdb->dom_alive = 1;
1011
1012 if (ypdb->dom_lockfd != -1)
1013 close(ypdb->dom_lockfd);
1014
1015 snprintf(path, sizeof path, "%s/%s.%d", BINDINGDIR"/var/yp/binding",
1016 ypdb->dom_domain, (int)ypdb->dom_vers);
1017 if ((fd = open(path, O_CREAT0x0200|O_SHLOCK0x0010|O_RDWR0x0002|O_TRUNC0x0400, 0644)) == -1) {
1018 (void)mkdir(BINDINGDIR"/var/yp/binding", 0755);
1019 if ((fd = open(path, O_CREAT0x0200|O_SHLOCK0x0010|O_RDWR0x0002|O_TRUNC0x0400,
1020 0644)) == -1)
1021 return;
1022 }
1023
1024 /*
1025 * ok, if BINDINGDIR exists, and we can create the binding file,
1026 * then write to it..
1027 */
1028 ypdb->dom_lockfd = fd;
1029
1030 iov[0].iov_base = (caddr_t)&(udptransp->xp_port);
1031 iov[0].iov_len = sizeof udptransp->xp_port;
1032 iov[1].iov_base = (caddr_t)&ybr;
1033 iov[1].iov_len = sizeof ybr;
1034 iov[2].iov_base = (caddr_t)&ypserv_tcp;
1035 iov[2].iov_len = sizeof ypserv_tcp;
1036
1037 memset(&ybr, 0, sizeof ybr);
1038 ybr.ypbind_status = YPBIND_SUCC_VAL;
1039 memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
1040 &raddrp->sin_addr,
1041 sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr));
1042 memmove(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
1043 &ypserv_udp,
1044 sizeof(ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port));
1045
1046 if (writev(ypdb->dom_lockfd, iov, sizeof(iov)/sizeof(iov[0])) !=
1047 iov[0].iov_len + iov[1].iov_len + iov[2].iov_len) {
1048 perror("write");
1049 close(ypdb->dom_lockfd);
1050 unlink(path);
1051 ypdb->dom_lockfd = -1;
1052 return;
1053 }
1054}
1055
1056struct _dom_binding *
1057xid2ypdb(u_int32_t xid)
1058{
1059 struct _dom_binding *ypdb;
1060
1061 for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext)
1062 if (ypdb->dom_xid == xid)
1063 break;
1064 return (ypdb);
1065}
1066
1067u_int32_t
1068unique_xid(struct _dom_binding *ypdb)
1069{
1070 u_int32_t xid;
1071
1072 xid = arc4random();
1073 while (xid2ypdb(xid) != NULL((void *)0))
1074 xid++;
1075
1076 return (xid);
1077}