1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 /* 29 * Portions of this source code were derived from Berkeley 30 * 4.3 BSD under license from the Regents of the University of 31 * California. 32 */ 33 34 #pragma ident "%Z%%M% %I% %E% SMI" 35 36 #ifdef PORTMAP 37 /* 38 * rpc_soc.c 39 * 40 * The backward compatibility routines for the earlier implementation 41 * of RPC, where the only transports supported were tcp/ip and udp/ip. 42 * Based on berkeley socket abstraction, now implemented on the top 43 * of TLI/Streams 44 */ 45 46 #include "mt.h" 47 #include "rpc_mt.h" 48 #include <stdio.h> 49 #include <sys/types.h> 50 #include <rpc/trace.h> 51 #include <rpc/rpc.h> 52 #include <netinet/in.h> 53 #include <sys/socket.h> 54 #include <netdb.h> 55 #include <netdir.h> 56 #include <errno.h> 57 #include <sys/syslog.h> 58 #include <rpc/pmap_clnt.h> 59 #include <rpc/pmap_prot.h> 60 #include <rpc/nettype.h> 61 #include <syslog.h> 62 #include <string.h> 63 #include <stdlib.h> 64 #include <unistd.h> 65 66 int __rpc_bindresvport(int, struct sockaddr_in *, int *, int); 67 int __rpc_bindresvport_ipv6(int, struct sockaddr *, int *, int, char *); 68 void get_myaddress_ipv6(char *, struct sockaddr *); 69 70 extern mutex_t rpcsoc_lock; 71 72 /* 73 * A common clnt create routine 74 */ 75 static CLIENT * 76 clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp) 77 struct sockaddr_in *raddr; 78 rpcprog_t prog; 79 rpcvers_t vers; 80 int *sockp; 81 uint_t sendsz; 82 uint_t recvsz; 83 char *tp; 84 { 85 CLIENT *cl; 86 int madefd = FALSE; 87 int fd = *sockp; 88 struct t_info tinfo; 89 struct netconfig *nconf; 90 int port; 91 struct netbuf bindaddr; 92 extern int __rpc_minfd; 93 bool_t locked = TRUE; 94 95 trace5(TR_clnt_com_create, 0, prog, vers, sendsz, recvsz); 96 mutex_lock(&rpcsoc_lock); 97 if ((nconf = __rpc_getconfip(tp)) == NULL) { 98 rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; 99 mutex_unlock(&rpcsoc_lock); 100 trace3(TR_clnt_com_create, 1, prog, vers); 101 return ((CLIENT *)NULL); 102 } 103 if (fd == RPC_ANYSOCK) { 104 fd = t_open(nconf->nc_device, O_RDWR, &tinfo); 105 if (fd == -1) 106 goto syserror; 107 if (fd < __rpc_minfd) 108 fd = __rpc_raise_fd(fd); 109 madefd = TRUE; 110 } else { 111 if (t_getinfo(fd, &tinfo) == -1) 112 goto syserror; 113 } 114 115 if (raddr->sin_port == 0) { 116 uint_t proto; 117 ushort_t sport; 118 119 mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */ 120 proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP; 121 sport = pmap_getport(raddr, prog, vers, proto); 122 if (sport == 0) { 123 locked = FALSE; 124 goto err; 125 } 126 raddr->sin_port = htons(sport); 127 mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */ 128 } 129 130 /* Transform sockaddr_in to netbuf */ 131 bindaddr.maxlen = bindaddr.len = __rpc_get_a_size(tinfo.addr); 132 bindaddr.buf = (char *)raddr; 133 134 (void) __rpc_bindresvport(fd, (struct sockaddr_in *)NULL, &port, 0); 135 cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers, 136 sendsz, recvsz); 137 if (cl) { 138 if (madefd == TRUE) { 139 /* 140 * The fd should be closed while destroying the handle. 141 */ 142 (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, (char *)NULL); 143 *sockp = fd; 144 } 145 (void) freenetconfigent(nconf); 146 mutex_unlock(&rpcsoc_lock); 147 trace3(TR_clnt_com_create, 1, prog, vers); 148 return (cl); 149 } 150 goto err; 151 152 syserror: 153 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 154 rpc_createerr.cf_error.re_errno = errno; 155 rpc_createerr.cf_error.re_terrno = t_errno; 156 157 err: if (madefd == TRUE) 158 (void) t_close(fd); 159 (void) freenetconfigent(nconf); 160 if (locked == TRUE) 161 mutex_unlock(&rpcsoc_lock); 162 trace3(TR_clnt_com_create, 1, prog, vers); 163 return ((CLIENT *)NULL); 164 } 165 166 CLIENT * 167 clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz) 168 struct sockaddr_in *raddr; 169 rpcprog_t prog; 170 rpcvers_t vers; 171 struct timeval wait; 172 int *sockp; 173 uint_t sendsz; 174 uint_t recvsz; 175 { 176 CLIENT *cl; 177 178 trace5(TR_clntudp_bufcreate, 0, prog, vers, sendsz, recvsz); 179 cl = clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, "udp"); 180 if (cl == (CLIENT *)NULL) { 181 trace3(TR_clntudp_bufcreate, 1, prog, vers); 182 return ((CLIENT *)NULL); 183 } 184 (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)&wait); 185 trace3(TR_clntudp_bufcreate, 1, prog, vers); 186 return (cl); 187 } 188 189 CLIENT * 190 clntudp_create(raddr, program, version, wait, sockp) 191 struct sockaddr_in *raddr; 192 rpcprog_t program; 193 rpcvers_t version; 194 struct timeval wait; 195 int *sockp; 196 { 197 CLIENT *dummy; 198 199 trace3(TR_clntudp_create, 0, program, version); 200 dummy = clntudp_bufcreate(raddr, program, version, wait, sockp, 201 UDPMSGSIZE, UDPMSGSIZE); 202 trace3(TR_clntudp_create, 1, program, version); 203 return (dummy); 204 } 205 206 CLIENT * 207 clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) 208 struct sockaddr_in *raddr; 209 rpcprog_t prog; 210 rpcvers_t vers; 211 int *sockp; 212 uint_t sendsz; 213 uint_t recvsz; 214 { 215 CLIENT *dummy; 216 217 trace5(TR_clnttcp_create, 0, prog, vers, sendsz, recvsz); 218 dummy = clnt_com_create(raddr, prog, vers, sockp, sendsz, 219 recvsz, "tcp"); 220 trace3(TR_clnttcp_create, 1, prog, vers); 221 return (dummy); 222 } 223 224 CLIENT * 225 clntraw_create(prog, vers) 226 rpcprog_t prog; 227 rpcvers_t vers; 228 { 229 CLIENT *dummy; 230 231 trace3(TR_clntraw_create, 0, prog, vers); 232 dummy = clnt_raw_create(prog, vers); 233 trace3(TR_clntraw_create, 1, prog, vers); 234 return (dummy); 235 } 236 237 /* 238 * A common server create routine 239 */ 240 static SVCXPRT * 241 svc_com_create(fd, sendsize, recvsize, netid) 242 int fd; 243 uint_t sendsize; 244 uint_t recvsize; 245 char *netid; 246 { 247 struct netconfig *nconf; 248 SVCXPRT *svc; 249 int madefd = FALSE; 250 int port; 251 int res; 252 253 trace4(TR_svc_com_create, 0, fd, sendsize, recvsize); 254 if ((nconf = __rpc_getconfip(netid)) == NULL) { 255 (void) syslog(LOG_ERR, "Could not get %s transport", netid); 256 trace2(TR_svc_com_create, 1, fd); 257 return ((SVCXPRT *)NULL); 258 } 259 if (fd == RPC_ANYSOCK) { 260 fd = t_open(nconf->nc_device, O_RDWR, (struct t_info *)NULL); 261 if (fd == -1) { 262 char errorstr[100]; 263 264 __tli_sys_strerror(errorstr, sizeof (errorstr), 265 t_errno, errno); 266 (void) syslog(LOG_ERR, 267 "svc%s_create: could not open connection : %s", netid, 268 errorstr); 269 (void) freenetconfigent(nconf); 270 trace2(TR_svc_com_create, 1, fd); 271 return ((SVCXPRT *)NULL); 272 } 273 madefd = TRUE; 274 } 275 276 res = __rpc_bindresvport(fd, (struct sockaddr_in *)NULL, &port, 8); 277 svc = svc_tli_create(fd, nconf, (struct t_bind *)NULL, 278 sendsize, recvsize); 279 (void) freenetconfigent(nconf); 280 if (svc == (SVCXPRT *)NULL) { 281 if (madefd) 282 (void) t_close(fd); 283 trace2(TR_svc_com_create, 1, fd); 284 return ((SVCXPRT *)NULL); 285 } 286 if (res == -1) { 287 port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port); 288 } 289 svc->xp_port = ntohs(port); 290 trace2(TR_svc_com_create, 1, fd); 291 return (svc); 292 } 293 294 SVCXPRT * 295 svctcp_create(fd, sendsize, recvsize) 296 int fd; 297 uint_t sendsize; 298 uint_t recvsize; 299 { 300 SVCXPRT *dummy; 301 302 trace4(TR_svctcp_create, 0, fd, sendsize, recvsize); 303 dummy = svc_com_create(fd, sendsize, recvsize, "tcp"); 304 trace4(TR_svctcp_create, 1, fd, sendsize, recvsize); 305 return (dummy); 306 } 307 308 SVCXPRT * 309 svcudp_bufcreate(fd, sendsz, recvsz) 310 int fd; 311 uint_t sendsz, recvsz; 312 { 313 SVCXPRT *dummy; 314 315 trace4(TR_svcudp_bufcreate, 0, fd, sendsz, recvsz); 316 dummy = svc_com_create(fd, sendsz, recvsz, "udp"); 317 trace4(TR_svcudp_bufcreate, 1, fd, sendsz, recvsz); 318 return (dummy); 319 } 320 321 SVCXPRT * 322 svcfd_create(fd, sendsize, recvsize) 323 int fd; 324 uint_t sendsize; 325 uint_t recvsize; 326 { 327 SVCXPRT *dummy; 328 329 trace4(TR_svcfd_create, 0, fd, sendsize, recvsize); 330 dummy = svc_fd_create(fd, sendsize, recvsize); 331 trace4(TR_svcfd_create, 1, fd, sendsize, recvsize); 332 return (dummy); 333 } 334 335 336 SVCXPRT * 337 svcudp_create(fd) 338 int fd; 339 { 340 SVCXPRT *dummy; 341 342 trace2(TR_svcudp_create, 0, fd); 343 dummy = svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"); 344 trace2(TR_svcudp_create, 1, fd); 345 return (dummy); 346 } 347 348 SVCXPRT * 349 svcraw_create() 350 { 351 SVCXPRT *dummy; 352 353 trace1(TR_svcraw_create, 0); 354 dummy = svc_raw_create(); 355 trace1(TR_svcraw_create, 1); 356 return (dummy); 357 } 358 359 /* 360 * Bind a fd to a privileged IP port. 361 * This is slightly different from the code in netdir_options 362 * because it has a different interface - main thing is that it 363 * needs to know its own address. We also wanted to set the qlen. 364 * t_getname() can be used for those purposes and perhaps job can be done. 365 */ 366 int 367 __rpc_bindresvport_ipv6(int fd, struct sockaddr *sin, int *portp, int qlen, 368 char *fmly) 369 { 370 int res; 371 static in_port_t port, *sinport; 372 struct sockaddr_in6 myaddr; 373 int i; 374 struct t_bind tbindstr, *tres; 375 struct t_info tinfo; 376 extern mutex_t portnum_lock; 377 378 /* VARIABLES PROTECTED BY portnum_lock: port */ 379 380 #define STARTPORT 600 381 #define ENDPORT (IPPORT_RESERVED - 1) 382 #define NPORTS (ENDPORT - STARTPORT + 1) 383 384 trace3(TR_bindresvport, 0, fd, qlen); 385 if (sin == 0 && fmly == 0) { 386 errno = EINVAL; 387 trace2(TR_bindresvport, 1, fd); 388 return (-1); 389 } 390 if (geteuid()) { 391 errno = EACCES; 392 trace2(TR_bindresvport, 1, fd); 393 return (-1); 394 } 395 if ((i = t_getstate(fd)) != T_UNBND) { 396 if (t_errno == TBADF) 397 errno = EBADF; 398 if (i != -1) 399 errno = EISCONN; 400 trace2(TR_bindresvport, 1, fd); 401 return (-1); 402 } 403 if (sin == 0) { 404 sin = (struct sockaddr *)&myaddr; 405 get_myaddress_ipv6(fmly, sin); 406 } 407 if (sin->sa_family == AF_INET) { 408 sinport = &((struct sockaddr_in *)sin)->sin_port; 409 } else if (sin->sa_family == AF_INET6) { 410 sinport = &((struct sockaddr_in6 *)sin)->sin6_port; 411 } else { 412 errno = EPFNOSUPPORT; 413 trace2(TR_bindresvport, 1, fd); 414 return (-1); 415 } 416 417 /* Transform sockaddr to netbuf */ 418 if (t_getinfo(fd, &tinfo) == -1) { 419 trace2(TR_bindresvport, 1, fd); 420 return (-1); 421 } 422 tres = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR); 423 if (tres == NULL) { 424 trace2(TR_bindresvport, 1, fd); 425 return (-1); 426 } 427 428 tbindstr.qlen = qlen; 429 tbindstr.addr.buf = (char *)sin; 430 tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr); 431 sin = (struct sockaddr *)tbindstr.addr.buf; 432 433 res = -1; 434 mutex_lock(&portnum_lock); 435 if (port == 0) 436 port = (getpid() % NPORTS) + STARTPORT; 437 for (i = 0; i < NPORTS; i++) { 438 *sinport = htons(port++); 439 if (port > ENDPORT) 440 port = STARTPORT; 441 res = t_bind(fd, &tbindstr, tres); 442 if (res == 0) { 443 if ((tbindstr.addr.len == tres->addr.len) && 444 (memcmp(tbindstr.addr.buf, tres->addr.buf, 445 (int)tres->addr.len) == 0)) 446 break; 447 (void) t_unbind(fd); 448 res = -1; 449 } else if (t_errno != TSYSERR || errno != EADDRINUSE) 450 break; 451 } 452 mutex_unlock(&portnum_lock); 453 454 if ((portp != NULL) && (res == 0)) 455 *portp = *sinport; 456 (void) t_free((char *)tres, T_BIND); 457 trace2(TR_bindresvport, 1, fd); 458 return (res); 459 } 460 461 int 462 __rpc_bindresvport(int fd, struct sockaddr_in *sin, int *portp, int qlen) 463 { 464 return (__rpc_bindresvport_ipv6(fd, (struct sockaddr *)sin, portp, 465 qlen, NC_INET)); 466 } 467 468 /* 469 * Get clients IP address. 470 * don't use gethostbyname, which would invoke yellow pages 471 * Remains only for backward compatibility reasons. 472 * Used mainly by the portmapper so that it can register 473 * with itself. Also used by pmap*() routines 474 */ 475 void 476 get_myaddress_ipv6(char *fmly, struct sockaddr *addr) 477 { 478 trace1(TR_get_myaddress, 0); 479 if (fmly != 0 && strcmp(fmly, NC_INET6) == 0) { 480 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; 481 memset(sin6, 0, sizeof (*sin6)); 482 sin6->sin6_family = AF_INET6; 483 sin6->sin6_port = htons(PMAPPORT); 484 if (__can_use_af(AF_INET6)) { 485 /* Local copy of in6addr_any to avoid -lsocket */ 486 struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; 487 sin6->sin6_addr = in6addr_any; 488 } else { 489 struct in_addr in4; 490 in4.s_addr = INADDR_ANY; 491 IN6_INADDR_TO_V4MAPPED(&in4, &sin6->sin6_addr); 492 } 493 } else { 494 struct sockaddr_in *sin = (struct sockaddr_in *)addr; 495 memset(sin, 0, sizeof (*sin)); 496 sin->sin_family = AF_INET; 497 sin->sin_port = htons(PMAPPORT); 498 sin->sin_addr.s_addr = INADDR_ANY; 499 } 500 trace1(TR_get_myaddress, 1); 501 } 502 503 void 504 get_myaddress(struct sockaddr_in *addr) 505 { 506 get_myaddress_ipv6(0, (struct sockaddr *)addr); 507 } 508 509 /* 510 * Get port used by specified service on specified host. 511 * Exists for source compatibility only. 512 * Obsoleted by rpcb_getaddr(). 513 */ 514 ushort_t 515 getrpcport(char *host, rpcprog_t prognum, rpcvers_t versnum, 516 rpcprot_t proto) 517 { 518 struct sockaddr_in addr; 519 struct hostent *hp; 520 521 if ((hp = gethostbyname(host)) == NULL) 522 return (0); 523 memcpy((char *)&addr.sin_addr, hp->h_addr, hp->h_length); 524 addr.sin_family = AF_INET; 525 addr.sin_port = 0; 526 return (pmap_getport(&addr, prognum, versnum, proto)); 527 } 528 529 /* 530 * For connectionless "udp" transport. Obsoleted by rpc_call(). 531 */ 532 int 533 callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out) 534 char *host; 535 rpcprog_t prognum; 536 rpcvers_t versnum; 537 rpcproc_t procnum; 538 xdrproc_t inproc, outproc; 539 char *in, *out; 540 { 541 int dummy; 542 543 trace4(TR_callrpc, 0, prognum, versnum, procnum); 544 dummy = (int)rpc_call(host, prognum, versnum, procnum, inproc, 545 in, outproc, out, "udp"); 546 trace4(TR_callrpc, 1, prognum, versnum, procnum); 547 return (dummy); 548 } 549 550 /* 551 * For connectionless kind of transport. Obsoleted by rpc_reg() 552 */ 553 int 554 registerrpc(prognum, versnum, procnum, progname, inproc, outproc) 555 rpcprog_t prognum; 556 rpcvers_t versnum; 557 rpcproc_t procnum; 558 char *(*progname)(); 559 xdrproc_t inproc, outproc; 560 { 561 int dummy; 562 563 trace4(TR_registerrpc, 0, prognum, versnum, procnum); 564 dummy = rpc_reg(prognum, versnum, procnum, progname, inproc, 565 outproc, "udp"); 566 trace4(TR_registerrpc, 1, prognum, versnum, procnum); 567 return (dummy); 568 } 569 570 /* 571 * All the following clnt_broadcast stuff is convulated; it supports 572 * the earlier calling style of the callback function 573 */ 574 static pthread_key_t clnt_broadcast_key; 575 static resultproc_t clnt_broadcast_result_main; 576 577 /* 578 * Need to translate the netbuf address into sockaddr_in address. 579 * Dont care about netid here. 580 */ 581 static bool_t 582 rpc_wrap_bcast(resultp, addr, nconf) 583 char *resultp; /* results of the call */ 584 struct netbuf *addr; /* address of the guy who responded */ 585 struct netconfig *nconf; /* Netconf of the transport */ 586 { 587 bool_t dummy; 588 resultproc_t clnt_broadcast_result; 589 590 trace1(TR_rpc_wrap_bcast, 0); 591 clnt_broadcast_result = thr_main()? clnt_broadcast_result_main : 592 (resultproc_t)pthread_getspecific(clnt_broadcast_key); 593 dummy = (*clnt_broadcast_result)(resultp, 594 (struct sockaddr_in *)addr->buf); 595 trace1(TR_rpc_wrap_bcast, 1); 596 return (dummy); 597 } 598 599 /* 600 * Broadcasts on UDP transport. Obsoleted by rpc_broadcast(). 601 */ 602 enum clnt_stat 603 clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) 604 rpcprog_t prog; /* program number */ 605 rpcvers_t vers; /* version number */ 606 rpcproc_t proc; /* procedure number */ 607 xdrproc_t xargs; /* xdr routine for args */ 608 caddr_t argsp; /* pointer to args */ 609 xdrproc_t xresults; /* xdr routine for results */ 610 caddr_t resultsp; /* pointer to results */ 611 resultproc_t eachresult; /* call with each result obtained */ 612 { 613 enum clnt_stat dummy; 614 extern mutex_t tsd_lock; 615 616 trace4(TR_clnt_broadcast, 0, prog, vers, proc); 617 if (thr_main()) 618 clnt_broadcast_result_main = eachresult; 619 else { 620 if (clnt_broadcast_key == 0) { 621 mutex_lock(&tsd_lock); 622 if (clnt_broadcast_key == 0) 623 pthread_key_create(&clnt_broadcast_key, NULL); 624 mutex_unlock(&tsd_lock); 625 } 626 pthread_setspecific(clnt_broadcast_key, (void *) eachresult); 627 } 628 dummy = rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, 629 resultsp, (resultproc_t)rpc_wrap_bcast, "udp"); 630 trace4(TR_clnt_broadcast, 1, prog, vers, proc); 631 return (dummy); 632 } 633 634 /* 635 * Create the client des authentication object. Obsoleted by 636 * authdes_seccreate(). 637 */ 638 AUTH * 639 authdes_create(servername, window, syncaddr, ckey) 640 char *servername; /* network name of server */ 641 uint_t window; /* time to live */ 642 struct sockaddr_in *syncaddr; /* optional hostaddr to sync with */ 643 des_block *ckey; /* optional conversation key to use */ 644 { 645 char *hostname = NULL; 646 AUTH *dummy; 647 648 trace2(TR_authdes_create, 0, window); 649 if (syncaddr) { 650 /* 651 * Change addr to hostname, because that is the way 652 * new interface takes it. 653 */ 654 struct netconfig *nconf; 655 struct netbuf nb_syncaddr; 656 struct nd_hostservlist *hlist; 657 AUTH *nauth; 658 int fd; 659 struct t_info tinfo; 660 661 if ((nconf = __rpc_getconfip("udp")) == NULL && 662 (nconf = __rpc_getconfip("tcp")) == NULL) 663 goto fallback; 664 665 /* Transform sockaddr_in to netbuf */ 666 if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) { 667 (void) freenetconfigent(nconf); 668 goto fallback; 669 } 670 (void) t_close(fd); 671 nb_syncaddr.maxlen = nb_syncaddr.len = 672 __rpc_get_a_size(tinfo.addr); 673 nb_syncaddr.buf = (char *)syncaddr; 674 if (netdir_getbyaddr(nconf, &hlist, &nb_syncaddr)) { 675 (void) freenetconfigent(nconf); 676 goto fallback; 677 } 678 if (hlist && hlist->h_cnt > 0 && hlist->h_hostservs) 679 hostname = hlist->h_hostservs->h_host; 680 nauth = authdes_seccreate(servername, window, hostname, ckey); 681 (void) netdir_free((char *)hlist, ND_HOSTSERVLIST); 682 (void) freenetconfigent(nconf); 683 trace2(TR_authdes_create, 1, window); 684 return (nauth); 685 } 686 fallback: 687 dummy = authdes_seccreate(servername, window, hostname, ckey); 688 trace2(TR_authdes_create, 1, window); 689 return (dummy); 690 } 691 692 #endif /* PORTMAP */ 693