ypbind.c revision 1927
150107Smsmith/* 250107Smsmith * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca> 350107Smsmith * All rights reserved. 450107Smsmith * 550107Smsmith * Redistribution and use in source and binary forms, with or without 650107Smsmith * modification, are permitted provided that the following conditions 750107Smsmith * are met: 850107Smsmith * 1. Redistributions of source code must retain the above copyright 950107Smsmith * notice, this list of conditions and the following disclaimer. 1050107Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1150107Smsmith * notice, this list of conditions and the following disclaimer in the 1250107Smsmith * documentation and/or other materials provided with the distribution. 1350107Smsmith * 3. The name of the author may not be used to endorse or promote 1450107Smsmith * products derived from this software without specific prior written 1550107Smsmith * permission. 1650107Smsmith * 1750107Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 1850107Smsmith * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1950107Smsmith * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2050107Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 2150107Smsmith * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2250107Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2350107Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2450107Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2550107Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2650107Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27116182Sobrien * SUCH DAMAGE. 28116182Sobrien */ 29116182Sobrien 3050107Smsmith#ifndef LINT 3150107Smsmithstatic char rcsid[] = "$Id: ypbind.c,v 1.2 1994/01/11 19:01:23 nate Exp $"; 3274914Sjhb#endif 3350107Smsmith 3469893Sjhb#include <sys/param.h> 3576166Smarkm#include <sys/types.h> 3650107Smsmith#include <sys/ioctl.h> 3750107Smsmith#include <sys/signal.h> 3850107Smsmith#include <sys/socket.h> 3969774Sphk#include <sys/file.h> 4050107Smsmith#include <sys/fcntl.h> 4150107Smsmith#include <sys/uio.h> 4260938Sjake#include <sys/syslog.h> 4350107Smsmith#include <stdio.h> 4467535Sjhb#include <errno.h> 4550107Smsmith#include <ctype.h> 4650107Smsmith#include <dirent.h> 4750107Smsmith#include <netdb.h> 4850107Smsmith#include <string.h> 4950107Smsmith#include <rpc/rpc.h> 5050107Smsmith#include <rpc/xdr.h> 5150107Smsmith#include <net/if.h> 52138439Sjkoshy#include <arpa/inet.h> 53112111Sjhb#include <rpc/pmap_clnt.h> 5469893Sjhb#include <rpc/pmap_prot.h> 5569893Sjhb#include <rpc/pmap_rmt.h> 5669893Sjhb#include <unistd.h> 5769893Sjhb#include <rpcsvc/yp_prot.h> 5869893Sjhb#include <rpcsvc/ypclnt.h> 5969893Sjhb 6069893Sjhb#ifndef BINDINGDIR 61112111Sjhb#define BINDINGDIR "/var/yp/binding" 62112111Sjhb#endif 6369893Sjhb 6469893Sjhbstruct _dom_binding { 65177253Srwatson struct _dom_binding *dom_pnext; 6669893Sjhb char dom_domain[YPMAXDOMAIN + 1]; 6750107Smsmith struct sockaddr_in dom_server_addr; 6850107Smsmith unsigned short int dom_server_port; 6950107Smsmith int dom_socket; 7050107Smsmith CLIENT *dom_client; 7150107Smsmith long int dom_vers; 72138439Sjkoshy time_t dom_check_t; 7350107Smsmith int dom_lockfd; 7450107Smsmith int dom_alive; 75112111Sjhb}; 7650107Smsmith 7750107Smsmithextern bool_t xdr_domainname(), xdr_ypbind_resp(); 7850107Smsmithextern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 7969893Sjhbextern bool_t xdr_ypbind_setdom(); 8050107Smsmith 8166205Smsmithchar *domainname; 8272200Sbmilekic 8366205Smsmithstruct _dom_binding *ypbindlist; 8450107Smsmithint check; 8550107Smsmith 8650107Smsmith#define YPSET_NO 0 87112111Sjhb#define YPSET_LOCAL 1 8850107Smsmith#define YPSET_ALL 2 8950107Smsmithint ypsetmode = YPSET_NO; 9050107Smsmith 91112111Sjhbint rpcsock; 92112111Sjhbstruct rmtcallargs rmtca; 93112111Sjhbstruct rmtcallres rmtcr; 94112111Sjhbchar rmtcr_outval; 95112111Sjhbu_long rmtcr_port; 96112111SjhbSVCXPRT *udptransp, *tcptransp; 97112111Sjhb 98112111Sjhbvoid * 99112111Sjhbypbindproc_null_2(transp, argp, clnt) 100112111SjhbSVCXPRT *transp; 101112111Sjhbvoid *argp; 102112111SjhbCLIENT *clnt; 103112111Sjhb{ 104112111Sjhb static char res; 105112111Sjhb 106112111Sjhb bzero((char *)&res, sizeof(res)); 107112111Sjhb return (void *)&res; 108112111Sjhb} 109112111Sjhb 11066205Smsmithstruct ypbind_resp * 11150107Smsmithypbindproc_domain_2(transp, argp, clnt) 11250107SmsmithSVCXPRT *transp; 113112111Sjhbchar *argp; 11450107SmsmithCLIENT *clnt; 115112111Sjhb{ 116112111Sjhb static struct ypbind_resp res; 11750107Smsmith struct _dom_binding *ypdb; 11893743Salfred char path[MAXPATHLEN]; 119112111Sjhb 12050107Smsmith bzero((char *)&res, sizeof res); 121112111Sjhb res.ypbind_status = YPBIND_FAIL_VAL; 122112111Sjhb 12350107Smsmith for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) 12450107Smsmith if( strcmp(ypdb->dom_domain, argp) == 0) 12550107Smsmith break; 126112111Sjhb 127112111Sjhb if(ypdb==NULL) { 128112111Sjhb ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 12950107Smsmith bzero((char *)ypdb, sizeof *ypdb); 130112111Sjhb strncpy(ypdb->dom_domain, argp, sizeof ypdb->dom_domain); 131112111Sjhb ypdb->dom_vers = YPVERS; 132112111Sjhb ypdb->dom_alive = 0; 133112111Sjhb ypdb->dom_lockfd = -1; 134112111Sjhb sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers); 135112111Sjhb unlink(path); 13650107Smsmith ypdb->dom_pnext = ypbindlist; 13750107Smsmith ypbindlist = ypdb; 13850107Smsmith check++; 13950107Smsmith return NULL; 14050107Smsmith } 14150107Smsmith 142112111Sjhb if(ypdb->dom_alive==0) 14350107Smsmith return NULL; 14450107Smsmith 14550107Smsmith#if 0 14650107Smsmith delta = ypdb->dom_check_t - ypdb->dom_ask_t; 14750107Smsmith if( !(ypdb->dom_ask_t==0 || delta > 5)) { 14850107Smsmith ypdb->dom_ask_t = time(NULL); 14950107Smsmith /* 15050107Smsmith * Hmm. More than 2 requests in 5 seconds have indicated that my 151112111Sjhb * binding is possibly incorrect. Ok, make myself unalive, and 15250107Smsmith * find out what the actual state is. 15350107Smsmith */ 154112111Sjhb if(ypdb->dom_lockfd!=-1) 155112111Sjhb close(ypdb->dom_lockfd); 156112111Sjhb ypdb->dom_lockfd = -1; 157112111Sjhb ypdb->dom_alive = 0; 158112111Sjhb ypdb->dom_lockfd = -1; 159112111Sjhb sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers); 160112111Sjhb unlink(path); 161112111Sjhb check++; 162112111Sjhb return NULL; 163112111Sjhb } 16450107Smsmith#endif 16550107Smsmith 166112111Sjhbanswer: 167112111Sjhb res.ypbind_status = YPBIND_SUCC_VAL; 168112111Sjhb res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr = 169112111Sjhb ypdb->dom_server_addr.sin_addr.s_addr; 170112111Sjhb res.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = 171112111Sjhb ypdb->dom_server_port; 172112111Sjhb /*printf("domain %s at %s/%d\n", ypdb->dom_domain, 173112111Sjhb inet_ntoa(ypdb->dom_server_addr.sin_addr), 174112111Sjhb ntohs(ypdb->dom_server_addr.sin_port));*/ 175112111Sjhb return &res; 176112111Sjhb} 177112111Sjhb 178112111Sjhbbool_t * 17950107Smsmithypbindproc_setdom_2(transp, argp, clnt) 18050107SmsmithSVCXPRT *transp; 181200652Sthompsastruct ypbind_setdom *argp; 182200652SthompsaCLIENT *clnt; 183112111Sjhb{ 18450107Smsmith struct sockaddr_in *fromsin, bindsin; 18550107Smsmith char res; 186112111Sjhb 187112111Sjhb bzero((char *)&res, sizeof(res)); 188112111Sjhb fromsin = svc_getcaller(transp); 189112111Sjhb 190138439Sjkoshy switch(ypsetmode) { 191112111Sjhb case YPSET_LOCAL: 192112111Sjhb if( fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) 193112111Sjhb return (void *)NULL; 194112111Sjhb break; 195112111Sjhb case YPSET_ALL: 196112111Sjhb break; 197112111Sjhb case YPSET_NO: 198112111Sjhb default: 199112111Sjhb return (void *)NULL; 200112111Sjhb } 201112111Sjhb 202112111Sjhb if(ntohs(fromsin->sin_port) >= IPPORT_RESERVED) 203112111Sjhb return (void *)&res; 204112111Sjhb 20550107Smsmith if(argp->ypsetdom_vers != YPVERS) 206138439Sjkoshy return (void *)&res; 20750107Smsmith 20850107Smsmith bzero((char *)&bindsin, sizeof bindsin); 20980703Sjake bindsin.sin_family = AF_INET; 21080703Sjake bindsin.sin_addr.s_addr = argp->ypsetdom_addr.s_addr; 21180703Sjake bindsin.sin_port = argp->ypsetdom_port; 21266205Smsmith rpc_received(argp->ypsetdom_domain, &bindsin, 1); 21350107Smsmith 21472200Sbmilekic res = 1; 215112111Sjhb return (void *)&res; 216112111Sjhb} 217112111Sjhb 21872200Sbmilekicstatic void 21966205Smsmithypbindprog_2(rqstp, transp) 22050107Smsmithstruct svc_req *rqstp; 22150107Smsmithregister SVCXPRT *transp; 22266205Smsmith{ 223112111Sjhb union { 224112111Sjhb char ypbindproc_domain_2_arg[MAXHOSTNAMELEN]; 225112111Sjhb struct ypbind_setdom ypbindproc_setdom_2_arg; 226112111Sjhb } argument; 227112111Sjhb struct authunix_parms *creds; 228112111Sjhb char *result; 229112111Sjhb bool_t (*xdr_argument)(), (*xdr_result)(); 230200652Sthompsa char *(*local)(); 231112111Sjhb 232112111Sjhb switch (rqstp->rq_proc) { 233112111Sjhb case YPBINDPROC_NULL: 234200652Sthompsa xdr_argument = xdr_void; 235112111Sjhb xdr_result = xdr_void; 236112111Sjhb local = (char *(*)()) ypbindproc_null_2; 237112111Sjhb break; 238200652Sthompsa 239112111Sjhb case YPBINDPROC_DOMAIN: 240112111Sjhb xdr_argument = xdr_domainname; 241200652Sthompsa xdr_result = xdr_ypbind_resp; 242200652Sthompsa local = (char *(*)()) ypbindproc_domain_2; 243112111Sjhb break; 244 245 case YPBINDPROC_SETDOM: 246 switch(rqstp->rq_cred.oa_flavor) { 247 case AUTH_UNIX: 248 creds = (struct authunix_parms *)rqstp->rq_clntcred; 249 if( creds->aup_uid != 0) { 250 svcerr_auth(transp, AUTH_BADCRED); 251 return; 252 } 253 break; 254 default: 255 svcerr_auth(transp, AUTH_TOOWEAK); 256 return; 257 } 258 259 xdr_argument = xdr_ypbind_setdom; 260 xdr_result = xdr_void; 261 local = (char *(*)()) ypbindproc_setdom_2; 262 break; 263 264 default: 265 svcerr_noproc(transp); 266 return; 267 } 268 bzero((char *)&argument, sizeof(argument)); 269 if (!svc_getargs(transp, xdr_argument, &argument)) { 270 svcerr_decode(transp); 271 return; 272 } 273 result = (*local)(transp, &argument, rqstp); 274 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 275 svcerr_systemerr(transp); 276 } 277 return; 278} 279 280main(argc, argv) 281char **argv; 282{ 283 char path[MAXPATHLEN]; 284 struct timeval tv; 285 fd_set fdsr; 286 int width; 287 int i; 288 289 yp_get_default_domain(&domainname); 290 if( domainname[0] == '\0') { 291 fprintf(stderr, "domainname not set. Aborting.\n"); 292 exit(1); 293 } 294 295 for(i=1; i<argc; i++) { 296 if( strcmp("-ypset", argv[i]) == 0) 297 ypsetmode = YPSET_ALL; 298 else if (strcmp("-ypsetme", argv[i]) == 0) 299 ypsetmode = YPSET_LOCAL; 300 } 301 302 /* blow away everything in BINDINGDIR */ 303 304 305 306#ifdef DAEMON 307 switch(fork()) { 308 case 0: 309 break; 310 case -1: 311 perror("fork"); 312 exit(1); 313 default: 314 exit(0); 315 } 316 setsid(); 317#endif 318 319 pmap_unset(YPBINDPROG, YPBINDVERS); 320 321 udptransp = svcudp_create(RPC_ANYSOCK); 322 if (udptransp == NULL) { 323 fprintf(stderr, "cannot create udp service."); 324 exit(1); 325 } 326 if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 327 IPPROTO_UDP)) { 328 fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, udp)."); 329 exit(1); 330 } 331 332 tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); 333 if (tcptransp == NULL) { 334 fprintf(stderr, "cannot create tcp service."); 335 exit(1); 336 } 337 338 if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 339 IPPROTO_TCP)) { 340 fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, tcp)."); 341 exit(1); 342 } 343 344 if( (rpcsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 345 perror("socket"); 346 return -1; 347 } 348 349 fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY); 350 i = 1; 351 setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &i, sizeof(i)); 352 rmtca.prog = YPPROG; 353 rmtca.vers = YPVERS; 354 rmtca.proc = YPPROC_DOMAIN_NONACK; 355 rmtca.xdr_args = NULL; /* set at call time */ 356 rmtca.args_ptr = NULL; /* set at call time */ 357 rmtcr.port_ptr = &rmtcr_port; 358 rmtcr.xdr_results = xdr_bool; 359 rmtcr.results_ptr = (caddr_t)&rmtcr_outval; 360 361 /* build initial domain binding, make it "unsuccessful" */ 362 ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); 363 bzero((char *)ypbindlist, sizeof *ypbindlist); 364 strncpy(ypbindlist->dom_domain, domainname, sizeof ypbindlist->dom_domain); 365 ypbindlist->dom_vers = YPVERS; 366 ypbindlist->dom_alive = 0; 367 ypbindlist->dom_lockfd = -1; 368 sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain, 369 ypbindlist->dom_vers); 370 (void)unlink(path); 371 372 width = getdtablesize(); 373 while(1) { 374 fdsr = svc_fdset; 375 FD_SET(rpcsock, &fdsr); 376 tv.tv_sec = 1; 377 tv.tv_usec = 0; 378 379 switch(select(width, &fdsr, NULL, NULL, &tv)) { 380 case 0: 381 checkwork(); 382 break; 383 case -1: 384 perror("select\n"); 385 break; 386 default: 387 if(FD_ISSET(rpcsock, &fdsr)) { 388 FD_CLR(rpcsock, &fdsr); 389 handle_replies(); 390 } 391 svc_getreqset(&fdsr); 392 if(check) 393 checkwork(); 394 break; 395 } 396 } 397} 398 399/* 400 * change to do something like this: 401 * 402 * STATE TIME ACTION NEWTIME NEWSTATE 403 * no binding t==* broadcast t=2 no binding 404 * binding t==60 check server t=10 binding 405 * binding t=10 broadcast t=2 no binding 406 */ 407checkwork() 408{ 409 struct _dom_binding *ypdb; 410 time_t t; 411 412 check = 0; 413 414 time(&t); 415 for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 416 if(ypdb->dom_alive==0 || ypdb->dom_check_t < t) { 417 broadcast(ypdb->dom_domain); 418 time(&t); 419 ypdb->dom_check_t = t + 5; 420 } 421 } 422} 423 424broadcast(dom) 425char *dom; 426{ 427 struct rpc_msg rpcmsg; 428 char buf[1400], inbuf[8192]; 429 enum clnt_stat st; 430 struct timeval tv; 431 int outlen, i, sock, len; 432 struct sockaddr_in bsin; 433 struct ifconf ifc; 434 struct ifreq ifreq, *ifr; 435 struct in_addr in; 436 AUTH *rpcua; 437 XDR rpcxdr; 438 439 rmtca.xdr_args = xdr_domainname; 440 rmtca.args_ptr = dom; 441 442 bzero((char *)&bsin, sizeof bsin); 443 bsin.sin_family = AF_INET; 444 bsin.sin_port = htons(PMAPPORT); 445 446 bzero((char *)&rpcxdr, sizeof rpcxdr); 447 bzero((char *)&rpcmsg, sizeof rpcmsg); 448 449 rpcua = authunix_create_default(); 450 if( rpcua == (AUTH *)NULL) { 451 /*printf("cannot get unix auth\n");*/ 452 return RPC_SYSTEMERROR; 453 } 454 rpcmsg.rm_direction = CALL; 455 rpcmsg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 456 rpcmsg.rm_call.cb_prog = PMAPPROG; 457 rpcmsg.rm_call.cb_vers = PMAPVERS; 458 rpcmsg.rm_call.cb_proc = PMAPPROC_CALLIT; 459 rpcmsg.rm_call.cb_cred = rpcua->ah_cred; 460 rpcmsg.rm_call.cb_verf = rpcua->ah_verf; 461 462 gettimeofday(&tv, (struct timezone *)0); 463 rpcmsg.rm_xid = (int)dom; 464 tv.tv_usec = 0; 465 xdrmem_create(&rpcxdr, buf, sizeof buf, XDR_ENCODE); 466 if( (!xdr_callmsg(&rpcxdr, &rpcmsg)) ) { 467 st = RPC_CANTENCODEARGS; 468 AUTH_DESTROY(rpcua); 469 return st; 470 } 471 if( (!xdr_rmtcall_args(&rpcxdr, &rmtca)) ) { 472 st = RPC_CANTENCODEARGS; 473 AUTH_DESTROY(rpcua); 474 return st; 475 } 476 outlen = (int)xdr_getpos(&rpcxdr); 477 xdr_destroy(&rpcxdr); 478 if(outlen<1) { 479 AUTH_DESTROY(rpcua); 480 return st; 481 } 482 AUTH_DESTROY(rpcua); 483 484 /* find all networks and send the RPC packet out them all */ 485 if( (sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 486 perror("socket"); 487 return -1; 488 } 489 490 ifc.ifc_len = sizeof inbuf; 491 ifc.ifc_buf = inbuf; 492 if( ioctl(sock, SIOCGIFCONF, &ifc) < 0) { 493 close(sock); 494 perror("ioctl(SIOCGIFCONF)"); 495 return -1; 496 } 497 ifr = ifc.ifc_req; 498 ifreq.ifr_name[0] = '\0'; 499 for(i=0; i<ifc.ifc_len; i+=len, ifr=(struct ifreq *)((caddr_t)ifr+len)) { 500#if defined(BSD) && BSD >= 199103 501 len = sizeof ifr->ifr_name + ifr->ifr_addr.sa_len; 502#else 503 len = sizeof ifc.ifc_len / sizeof(struct ifreq); 504#endif 505 ifreq = *ifr; 506 if( ifreq.ifr_addr.sa_family != AF_INET) 507 continue; 508 if( ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0) { 509 perror("ioctl(SIOCGIFFLAGS)"); 510 continue; 511 } 512 if( (ifreq.ifr_flags & IFF_UP) == 0) 513 continue; 514 515 ifreq.ifr_flags &= (IFF_LOOPBACK | IFF_BROADCAST); 516 if( ifreq.ifr_flags==IFF_BROADCAST ) { 517 if( ioctl(sock, SIOCGIFBRDADDR, &ifreq) < 0 ) { 518 perror("ioctl(SIOCGIFBRDADDR)"); 519 continue; 520 } 521 } else if( ifreq.ifr_flags==IFF_LOOPBACK ) { 522 if( ioctl(sock, SIOCGIFADDR, &ifreq) < 0 ) { 523 perror("ioctl(SIOCGIFADDR)"); 524 continue; 525 } 526 } else 527 continue; 528 529 in = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; 530 bsin.sin_addr = in; 531 if( sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bsin, 532 sizeof bsin) < 0 ) 533 perror("sendto"); 534 } 535 close(sock); 536 return 0; 537} 538 539/*enum clnt_stat*/ 540handle_replies() 541{ 542 char buf[1400]; 543 int fromlen, inlen; 544 struct sockaddr_in raddr; 545 struct rpc_msg msg; 546 XDR xdr; 547 548recv_again: 549 bzero((char *)&xdr, sizeof(xdr)); 550 bzero((char *)&msg, sizeof(msg)); 551 msg.acpted_rply.ar_verf = _null_auth; 552 msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr; 553 msg.acpted_rply.ar_results.proc = xdr_rmtcallres; 554 555try_again: 556 fromlen = sizeof (struct sockaddr); 557 inlen = recvfrom(rpcsock, buf, sizeof buf, 0, 558 (struct sockaddr *)&raddr, &fromlen); 559 if(inlen<0) { 560 if(errno==EINTR) 561 goto try_again; 562 return RPC_CANTRECV; 563 } 564 if(inlen<sizeof(u_long)) 565 goto recv_again; 566 567 /* 568 * see if reply transaction id matches sent id. 569 * If so, decode the results. 570 */ 571 xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE); 572 if( xdr_replymsg(&xdr, &msg)) { 573 if( (msg.rm_reply.rp_stat == MSG_ACCEPTED) && 574 (msg.acpted_rply.ar_stat == SUCCESS)) { 575 raddr.sin_port = htons((u_short)rmtcr_port); 576 rpc_received(msg.rm_xid, &raddr, 0); 577 } 578 } 579 xdr.x_op = XDR_FREE; 580 msg.acpted_rply.ar_results.proc = xdr_void; 581 xdr_destroy(&xdr); 582 583 return RPC_SUCCESS; 584} 585 586/* 587 * LOOPBACK IS MORE IMPORTANT: PUT IN HACK 588 */ 589rpc_received(dom, raddrp, force) 590char *dom; 591struct sockaddr_in *raddrp; 592int force; 593{ 594 struct _dom_binding *ypdb; 595 struct iovec iov[2]; 596 struct ypbind_resp ybr; 597 char path[MAXPATHLEN]; 598 int fd; 599 600 /*printf("returned from %s about %s\n", inet_ntoa(raddrp->sin_addr), dom);*/ 601 602 if(dom==NULL) 603 return; 604 605 for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) 606 if( strcmp(ypdb->dom_domain, dom) == 0) 607 break; 608 609 if(ypdb==NULL) { 610 if(force==0) 611 return; 612 ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 613 bzero((char *)ypdb, sizeof *ypdb); 614 strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); 615 ypdb->dom_lockfd = -1; 616 ypdb->dom_pnext = ypbindlist; 617 ypbindlist = ypdb; 618 } 619 620 /* soft update, alive, less than 30 seconds old */ 621 if(ypdb->dom_alive==1 && force==0 && ypdb->dom_check_t<time(NULL)+30) 622 return; 623 624 bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr, 625 sizeof ypdb->dom_server_addr); 626 ypdb->dom_check_t = time(NULL) + 60; /* recheck binding in 60 seconds */ 627 ypdb->dom_vers = YPVERS; 628 ypdb->dom_alive = 1; 629 630 if(ypdb->dom_lockfd != -1) 631 close(ypdb->dom_lockfd); 632 633 sprintf(path, "%s/%s.%d", BINDINGDIR, 634 ypdb->dom_domain, ypdb->dom_vers); 635#ifdef O_SHLOCK 636 if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { 637 (void)mkdir(BINDINGDIR, 0755); 638 if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) 639 return; 640 } 641#else 642 if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { 643 (void)mkdir(BINDINGDIR, 0755); 644 if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) 645 return; 646 } 647 flock(fd, LOCK_SH); 648#endif 649 650 /* 651 * ok, if BINDINGDIR exists, and we can create the binding file, 652 * then write to it.. 653 */ 654 ypdb->dom_lockfd = fd; 655 656 iov[0].iov_base = (caddr_t)&(udptransp->xp_port); 657 iov[0].iov_len = sizeof udptransp->xp_port; 658 iov[1].iov_base = (caddr_t)&ybr; 659 iov[1].iov_len = sizeof ybr; 660 661 bzero(&ybr, sizeof ybr); 662 ybr.ypbind_status = YPBIND_SUCC_VAL; 663 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr; 664 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; 665 666 if( writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { 667 perror("write"); 668 close(ypdb->dom_lockfd); 669 ypdb->dom_lockfd = -1; 670 return; 671 } 672} 673