ypbind.c revision 8246
1/* 2 * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#ifndef LINT 31static char rcsid[] = "$Id: ypbind.c,v 1.8 1995/04/26 19:03:14 wpaul Exp $"; 32#endif 33 34#include <sys/param.h> 35#include <sys/types.h> 36#include <sys/wait.h> 37#include <sys/ioctl.h> 38#include <sys/signal.h> 39#include <sys/socket.h> 40#include <sys/file.h> 41#include <sys/fcntl.h> 42#include <sys/stat.h> 43#include <sys/uio.h> 44#include <syslog.h> 45#include <stdio.h> 46#include <errno.h> 47#include <ctype.h> 48#include <dirent.h> 49#include <netdb.h> 50#include <string.h> 51#include <rpc/rpc.h> 52#include <rpc/xdr.h> 53#include <net/if.h> 54#include <netinet/in.h> 55#include <arpa/inet.h> 56#include <rpc/pmap_clnt.h> 57#include <rpc/pmap_prot.h> 58#include <rpc/pmap_rmt.h> 59#include <unistd.h> 60#include <stdlib.h> 61#include <rpcsvc/yp_prot.h> 62#include <rpcsvc/ypclnt.h> 63 64#ifndef BINDINGDIR 65#define BINDINGDIR "/var/yp/binding" 66#endif 67 68/* 69 * Ping the server once every PING_INTERVAL seconds to make sure it's 70 * still there. 71 */ 72#ifndef PING_INTERVAL 73#define PING_INTERVAL 60 74#endif 75#ifndef FAIL_THRESHOLD 76#define FAIL_THRESHOLD 20 77#endif 78 79struct _dom_binding { 80 struct _dom_binding *dom_pnext; 81 char dom_domain[YPMAXDOMAIN + 1]; 82 struct sockaddr_in dom_server_addr; 83 CLIENT *client_handle; 84 long int dom_vers; 85 int dom_lockfd; 86 int dom_alive; 87 int dom_broadcasting; 88 int dom_default; 89 time_t dom_check; 90}; 91 92extern bool_t xdr_domainname(), xdr_ypbind_resp(); 93extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 94extern bool_t xdr_ypbind_setdom(); 95 96void checkwork __P((void)); 97void *ypbindproc_null_2 __P((SVCXPRT *, void *, CLIENT *)); 98bool_t *ypbindproc_setdom_2 __P((SVCXPRT *, struct ypbind_setdom *, CLIENT *)); 99void rpc_received __P((char *, struct sockaddr_in *, int )); 100void broadcast __P((struct _dom_binding *)); 101int ping __P((struct _dom_binding *, int)); 102void handle_children __P(( int )); 103 104static char *broad_domain; 105char *domainname; 106struct _dom_binding *ypbindlist; 107 108#define YPSET_NO 0 109#define YPSET_LOCAL 1 110#define YPSET_ALL 2 111int ypsetmode = YPSET_NO; 112int ypsecuremode = 0; 113 114/* No more than MAX_CHILDREN child broadcasters at a time. */ 115#define MAX_CHILDREN 5 116int child_fds[FD_SETSIZE]; 117static int fd[2]; 118int children = 0; 119 120SVCXPRT *udptransp, *tcptransp; 121 122void * 123ypbindproc_null_2(transp, argp, clnt) 124SVCXPRT *transp; 125void *argp; 126CLIENT *clnt; 127{ 128 static char res; 129 130 bzero((char *)&res, sizeof(res)); 131 return (void *)&res; 132} 133 134struct ypbind_resp * 135ypbindproc_domain_2(transp, argp, clnt) 136SVCXPRT *transp; 137char *argp; 138CLIENT *clnt; 139{ 140 static struct ypbind_resp res; 141 struct _dom_binding *ypdb; 142 char path[MAXPATHLEN]; 143 144 bzero((char *)&res, sizeof res); 145 res.ypbind_status = YPBIND_FAIL_VAL; 146 res.ypbind_respbody.ypbind_error = YPBIND_ERR_NOSERV; 147 148 for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) 149 if( strcmp(ypdb->dom_domain, argp) == 0) 150 break; 151 152 if(ypdb==NULL) { 153 ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 154 if (ypdb == NULL) { 155 syslog(LOG_WARNING, "malloc: %s", strerror(errno)); 156 res.ypbind_respbody.ypbind_error = YPBIND_ERR_RESC; 157 return; 158 } 159 bzero((char *)ypdb, sizeof *ypdb); 160 strncpy(ypdb->dom_domain, argp, sizeof ypdb->dom_domain); 161 ypdb->dom_vers = YPVERS; 162 ypdb->dom_alive = 0; 163 ypdb->dom_default = 0; 164 ypdb->dom_lockfd = -1; 165 sprintf(path, "%s/%s.%ld", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers); 166 unlink(path); 167 ypdb->dom_pnext = ypbindlist; 168 ypbindlist = ypdb; 169 return &res; 170 } 171 172 if(ypdb->dom_alive==0) 173 return &res; 174 175 if (ping(ypdb, 1)) 176 return &res; 177 178 res.ypbind_status = YPBIND_SUCC_VAL; 179 res.ypbind_respbody.ypbind_error = 0; /* Success */ 180 res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr = 181 ypdb->dom_server_addr.sin_addr.s_addr; 182 res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = 183 ypdb->dom_server_addr.sin_port; 184 /*printf("domain %s at %s/%d\n", ypdb->dom_domain, 185 inet_ntoa(ypdb->dom_server_addr.sin_addr), 186 ntohs(ypdb->dom_server_addr.sin_port));*/ 187 return &res; 188} 189 190bool_t * 191ypbindproc_setdom_2(transp, argp, clnt) 192SVCXPRT *transp; 193struct ypbind_setdom *argp; 194CLIENT *clnt; 195{ 196 struct sockaddr_in *fromsin, bindsin; 197 static char res; 198 199 bzero((char *)&res, sizeof(res)); 200 fromsin = svc_getcaller(transp); 201 202 switch(ypsetmode) { 203 case YPSET_LOCAL: 204 if( fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) 205 return (void *)NULL; 206 break; 207 case YPSET_ALL: 208 break; 209 case YPSET_NO: 210 default: 211 return (void *)NULL; 212 } 213 214 if(ntohs(fromsin->sin_port) >= IPPORT_RESERVED) 215 return (void *)&res; 216 217 if(argp->ypsetdom_vers != YPVERS) 218 return (void *)&res; 219 220 bzero((char *)&bindsin, sizeof bindsin); 221 bindsin.sin_family = AF_INET; 222 bindsin.sin_addr.s_addr = argp->ypsetdom_addr.s_addr; 223 bindsin.sin_port = argp->ypsetdom_port; 224 rpc_received(argp->ypsetdom_domain, &bindsin, 1); 225 226 res = 1; 227 return (void *)&res; 228} 229 230static void 231ypbindprog_2(rqstp, transp) 232struct svc_req *rqstp; 233register SVCXPRT *transp; 234{ 235 union { 236 char ypbindproc_domain_2_arg[MAXHOSTNAMELEN]; 237 struct ypbind_setdom ypbindproc_setdom_2_arg; 238 } argument; 239 struct authunix_parms *creds; 240 char *result; 241 bool_t (*xdr_argument)(), (*xdr_result)(); 242 char *(*local)(); 243 244 switch (rqstp->rq_proc) { 245 case YPBINDPROC_NULL: 246 xdr_argument = xdr_void; 247 xdr_result = xdr_void; 248 local = (char *(*)()) ypbindproc_null_2; 249 break; 250 251 case YPBINDPROC_DOMAIN: 252 xdr_argument = xdr_domainname; 253 xdr_result = xdr_ypbind_resp; 254 local = (char *(*)()) ypbindproc_domain_2; 255 break; 256 257 case YPBINDPROC_SETDOM: 258 switch(rqstp->rq_cred.oa_flavor) { 259 case AUTH_UNIX: 260 creds = (struct authunix_parms *)rqstp->rq_clntcred; 261 if( creds->aup_uid != 0) { 262 svcerr_auth(transp, AUTH_BADCRED); 263 return; 264 } 265 break; 266 default: 267 svcerr_auth(transp, AUTH_TOOWEAK); 268 return; 269 } 270 271 xdr_argument = xdr_ypbind_setdom; 272 xdr_result = xdr_void; 273 local = (char *(*)()) ypbindproc_setdom_2; 274 break; 275 276 default: 277 svcerr_noproc(transp); 278 return; 279 } 280 bzero((char *)&argument, sizeof(argument)); 281 if (!svc_getargs(transp, xdr_argument, &argument)) { 282 svcerr_decode(transp); 283 return; 284 } 285 result = (*local)(transp, &argument, rqstp); 286 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 287 svcerr_systemerr(transp); 288 } 289 return; 290} 291 292/* Jack the reaper */ 293void reaper(sig) 294int sig; 295{ 296 int st; 297 298 wait3(&st, WNOHANG, NULL); 299} 300 301void 302main(argc, argv) 303int argc; 304char **argv; 305{ 306 char path[MAXPATHLEN]; 307 struct timeval tv; 308 fd_set fdsr; 309 int i; 310 311 yp_get_default_domain(&domainname); 312 if( domainname[0] == '\0') { 313 fprintf(stderr, "domainname not set. Aborting.\n"); 314 exit(1); 315 } 316 317 for(i=1; i<argc; i++) { 318 if( strcmp("-ypset", argv[i]) == 0) 319 ypsetmode = YPSET_ALL; 320 else if (strcmp("-ypsetme", argv[i]) == 0) 321 ypsetmode = YPSET_LOCAL; 322 else if (strcmp("-s", argv[i]) == 0) 323 ypsecuremode++; 324 } 325 326 /* blow away everything in BINDINGDIR */ 327 328 329 330#ifdef DAEMON 331 switch(fork()) { 332 case 0: 333 break; 334 case -1: 335 perror("fork"); 336 exit(1); 337 default: 338 exit(0); 339 } 340 setsid(); 341#endif 342 343 pmap_unset(YPBINDPROG, YPBINDVERS); 344 345 udptransp = svcudp_create(RPC_ANYSOCK); 346 if (udptransp == NULL) { 347 fprintf(stderr, "cannot create udp service."); 348 exit(1); 349 } 350 if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 351 IPPROTO_UDP)) { 352 fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, udp)."); 353 exit(1); 354 } 355 356 tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); 357 if (tcptransp == NULL) { 358 fprintf(stderr, "cannot create tcp service."); 359 exit(1); 360 } 361 362 if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 363 IPPROTO_TCP)) { 364 fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, tcp)."); 365 exit(1); 366 } 367 368 /* build initial domain binding, make it "unsuccessful" */ 369 ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); 370 if (ypbindlist == NULL) { 371 perror("malloc"); 372 exit(1); 373 } 374 bzero((char *)ypbindlist, sizeof *ypbindlist); 375 strncpy(ypbindlist->dom_domain, domainname, sizeof ypbindlist->dom_domain); 376 ypbindlist->dom_vers = YPVERS; 377 ypbindlist->dom_alive = 0; 378 ypbindlist->dom_lockfd = -1; 379 ypbindlist->client_handle = NULL; 380 ypbindlist->dom_default = 1; 381 sprintf(path, "%s/%s.%ld", BINDINGDIR, ypbindlist->dom_domain, 382 ypbindlist->dom_vers); 383 (void)unlink(path); 384 385 /* Initialize children fds. */ 386 for (i = 0; i < FD_SETSIZE; i++) 387 child_fds[i] = -1; 388 389 openlog(argv[0], LOG_PID, LOG_DAEMON); 390 391 while(1) { 392 fdsr = svc_fdset; 393 394 for (i = 0; i < FD_SETSIZE; i++) 395 if (child_fds[i] > 0 ) 396 FD_SET(child_fds[i], &fdsr); 397 398 tv.tv_sec = 1; 399 tv.tv_usec = 0; 400 401 switch(select(_rpc_dtablesize(), &fdsr, NULL, NULL, &tv)) { 402 case 0: 403 checkwork(); 404 reaper(); 405 break; 406 case -1: 407 syslog(LOG_WARNING, "select: %s", strerror(errno)); 408 break; 409 default: 410 for(i = 0; i < FD_SETSIZE; i++) { 411 if (child_fds[i] > 0 && FD_ISSET(child_fds[i],&fdsr)) { 412 handle_children(child_fds[i]); 413 close(child_fds[i]); 414 FD_CLR(child_fds[i], &fdsr); 415 child_fds[i] = -1; 416 children--; 417 418 } 419 } 420 svc_getreqset(&fdsr); 421 break; 422 } 423 } 424} 425 426void 427checkwork() 428{ 429 struct _dom_binding *ypdb; 430 time_t t; 431 432 time(&t); 433 for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 434 if (!ypdb->dom_alive && !ypdb->dom_broadcasting) { 435 if (!ypdb->dom_default) 436 ypdb->dom_alive = 1; 437 ypdb->dom_broadcasting = 1; 438 broadcast(ypdb); 439 } 440 if (ypdb->dom_alive && ypdb->dom_check < t) 441 ping(ypdb, 0); 442 } 443} 444 445/* The clnt_broadcast() callback mechanism sucks. */ 446 447/* 448 * Receive results from broadcaster. Don't worry about passing 449 * bogus info to rpc_received() -- it can handle it. 450 */ 451void handle_children(i) 452int i; 453{ 454 char buf[YPMAXDOMAIN + 1]; 455 struct sockaddr_in addr; 456 457 if (read(i, &buf, sizeof(buf)) < 0) 458 syslog(LOG_WARNING, "could not read from child: %s", strerror(errno)); 459 if (read(i, &addr, sizeof(struct sockaddr_in)) < 0) 460 syslog(LOG_WARNING, "could not read from child: %s", strerror(errno)); 461 rpc_received((char *)&buf, &addr, 0); 462} 463 464/* 465 * Send our dying words back to our parent before we perish. 466 */ 467int 468tell_parent(dom, addr) 469char *dom; 470struct sockaddr_in *addr; 471{ 472 char buf[YPMAXDOMAIN + 1]; 473 struct timeval timeout; 474 fd_set fds; 475 476 timeout.tv_sec = 5; 477 timeout.tv_usec = 0; 478 479 sprintf (buf, "%s", broad_domain); 480 if (write(fd[1], &buf, sizeof(buf)) < 0) 481 return(1); 482 483 /* 484 * Stay in sync with parent: wait for it to read our first 485 * message before sending the second. 486 */ 487 488 FD_ZERO(&fds); 489 FD_SET(fd[1], &fds); 490 if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1) 491 return(1); 492 if (FD_ISSET(fd[1], &fds)) { 493 if (write(fd[1], addr, sizeof(struct sockaddr_in)) < 0) 494 return(1); 495 } else { 496 return(1); 497 } 498 499 close(fd[1]); 500 return (0); 501} 502 503bool_t broadcast_result(out, addr) 504bool_t *out; 505struct sockaddr_in *addr; 506{ 507 if (tell_parent(&broad_domain, addr)) 508 syslog(LOG_WARNING, "lost connection to parent"); 509 return TRUE; 510} 511 512/* 513 * The right way to send RPC broadcasts. 514 * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast() 515 * blocks while waiting for replies, so we have to fork off seperate 516 * broadcaster processes that do the waiting and then transmit their 517 * results back to the parent for processing. We also have to remember 518 * to save the name of the domain we're trying to bind in a global 519 * variable since clnt_broadcast() provides no way to pass things to 520 * the 'eachresult' callback function. 521 */ 522void 523broadcast(ypdb) 524struct _dom_binding *ypdb; 525{ 526 bool_t out = FALSE; 527 enum clnt_stat stat; 528 int i; 529 530 if (children > MAX_CHILDREN) 531 return; 532 533 broad_domain = ypdb->dom_domain; 534 535 if (pipe(fd) < 0) { 536 syslog(LOG_WARNING, "pipe: %s",strerror(errno)); 537 return; 538 } 539 540 switch(fork()) { 541 case 0: 542 close(fd[0]); 543 break; 544 case -1: 545 syslog(LOG_WARNING, "fork: %s", strerror(errno)); 546 close(fd[1]); 547 close(fd[0]); 548 return; 549 default: 550 for (i = 0; i < FD_SETSIZE; i++) { 551 if (child_fds[i] < 0) { 552 child_fds[i] = fd[0]; 553 break; 554 } 555 } 556 close(fd[1]); 557 children++; 558 return; 559 } 560 561 close(ypdb->dom_lockfd); 562 stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, 563 xdr_domainname, (char *)ypdb->dom_domain, xdr_bool, (char *)&out, 564 broadcast_result); 565 566 if (stat != RPC_SUCCESS) { 567 syslog(LOG_WARNING, "NIS server for domain %s not responding", 568 ypdb->dom_domain); 569 bzero((char *)&ypdb->dom_server_addr, 570 sizeof(struct sockaddr_in)); 571 if (tell_parent(&ypdb->dom_domain, &ypdb->dom_server_addr)) 572 syslog(LOG_WARNING, "lost connection to parent"); 573 } 574 exit(0); 575} 576 577/* 578 * The right way to check if a server is alive. 579 * Attempt to get a client handle pointing to the server and send a 580 * YPPROC_DOMAIN_NONACK. If we don't get a response, we invalidate 581 * this binding entry, which will cause checkwork() to dispatch a 582 * broadcaster process. Note that we treat non-default domains 583 * specially: once bound, we keep tabs on our server, but if it 584 * goes away and fails to respond after one round of broadcasting, we 585 * abandon it until a client specifically references it again. We make 586 * every effort to keep our default domain bound, however, since we 587 * need it to keep the system on its feet. 588 */ 589int 590ping(ypdb, force) 591struct _dom_binding *ypdb; 592int force; 593{ 594 bool_t out; 595 struct timeval interval, timeout; 596 enum clnt_stat stat; 597 int rpcsock = RPC_ANYSOCK; 598 time_t t; 599 600 interval.tv_sec = 5; 601 interval.tv_usec = 0; 602 timeout.tv_sec = FAIL_THRESHOLD; 603 timeout.tv_usec = 0; 604 605 if (ypdb->dom_broadcasting) 606 return(1); 607 608 if (!ypdb->dom_default && ypdb->dom_vers == -1 && !force) 609 return(1); 610 611 if (ypdb->client_handle == NULL) { 612 if ((ypdb->client_handle = clntudp_bufcreate( 613 &ypdb->dom_server_addr, YPPROG, YPVERS, 614 interval, &rpcsock, RPCSMALLMSGSIZE, 615 RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { 616 /* Can't get a handle: we're dead. */ 617 ypdb->client_handle = NULL; 618 ypdb->dom_alive = 0; 619 ypdb->dom_vers = -1; 620 flock(ypdb->dom_lockfd, LOCK_UN); 621 return(1); 622 } 623 } 624 625 if ((stat = clnt_call(ypdb->client_handle, YPPROC_DOMAIN_NONACK, 626 xdr_domainname, (char *)ypdb->dom_domain, 627 xdr_bool, (char *)&out, timeout)) != RPC_SUCCESS) { 628 ypdb->client_handle = NULL; 629 ypdb->dom_alive = 0; 630 ypdb->dom_vers = -1; 631 flock(ypdb->dom_lockfd, LOCK_UN); 632 return(1); 633 } 634 /* 635 * We pinged successfully. Reset the timer. 636 */ 637 time(&t); 638 ypdb->dom_check = t + PING_INTERVAL; 639 640 return(0); 641} 642 643void rpc_received(dom, raddrp, force) 644char *dom; 645struct sockaddr_in *raddrp; 646int force; 647{ 648 struct _dom_binding *ypdb; 649 struct iovec iov[2]; 650 struct ypbind_resp ybr; 651 char path[MAXPATHLEN]; 652 int fd; 653 654 /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), 655 ntohs(raddrp->sin_port), dom);*/ 656 657 if(dom==NULL) 658 return; 659 660 for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) 661 if( strcmp(ypdb->dom_domain, dom) == 0) 662 break; 663 664 /* if in securemode, check originating port number */ 665 if (ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED)) { 666 syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", 667 inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), 668 dom); 669 if (ypdb != NULL) { 670 ypdb->dom_broadcasting = 0; 671 ypdb->dom_alive = 0; 672 } 673 return; 674 } 675 676 if (raddrp->sin_addr.s_addr == (long)0) { 677 ypdb->dom_broadcasting = 0; 678 ypdb->dom_alive = 0; 679 return; 680 } 681 682 if(ypdb==NULL) { 683 if (force == 0) 684 return; 685 ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 686 if (ypdb == NULL) { 687 syslog(LOG_WARNING, "malloc: %s", strerror(errno)); 688 return; 689 } 690 bzero((char *)ypdb, sizeof *ypdb); 691 strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); 692 ypdb->dom_lockfd = -1; 693 ypdb->dom_default = 0; 694 ypdb->dom_alive = 0; 695 ypdb->dom_broadcasting = 0; 696 ypdb->dom_pnext = ypbindlist; 697 ypbindlist = ypdb; 698 } 699 700 /* We've recovered from a crash: inform the world. */ 701 if (ypdb->dom_vers = -1 && ypdb->dom_server_addr.sin_addr.s_addr) 702 syslog(LOG_WARNING, "NIS server for domain %s OK", 703 ypdb->dom_domain); 704 705 bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr, 706 sizeof ypdb->dom_server_addr); 707 708 ypdb->dom_vers = YPVERS; 709 ypdb->dom_alive = 1; 710 ypdb->dom_broadcasting = 0; 711 712 if(ypdb->dom_lockfd != -1) 713 close(ypdb->dom_lockfd); 714 715 sprintf(path, "%s/%s.%ld", BINDINGDIR, 716 ypdb->dom_domain, ypdb->dom_vers); 717#ifdef O_SHLOCK 718 if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { 719 (void)mkdir(BINDINGDIR, 0755); 720 if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) 721 return; 722 } 723#else 724 if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { 725 (void)mkdir(BINDINGDIR, 0755); 726 if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) 727 return; 728 } 729 flock(fd, LOCK_SH); 730#endif 731 732 /* 733 * ok, if BINDINGDIR exists, and we can create the binding file, 734 * then write to it.. 735 */ 736 ypdb->dom_lockfd = fd; 737 738 iov[0].iov_base = (caddr_t)&(udptransp->xp_port); 739 iov[0].iov_len = sizeof udptransp->xp_port; 740 iov[1].iov_base = (caddr_t)&ybr; 741 iov[1].iov_len = sizeof ybr; 742 743 bzero(&ybr, sizeof ybr); 744 ybr.ypbind_status = YPBIND_SUCC_VAL; 745 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr; 746 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; 747 748 if( writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { 749 syslog(LOG_WARNING, "write: %s", strerror(errno)); 750 close(ypdb->dom_lockfd); 751 ypdb->dom_lockfd = -1; 752 return; 753 } 754} 755