Bug Summary

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