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 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * clnt_bcast.c 39 * Client interface to broadcast service. 40 * 41 * The following is kludged-up support for simple rpc broadcasts. 42 * Someday a large, complicated system will replace these routines. 43 */ 44 45 #include <string.h> 46 #include <strings.h> 47 #include <rpc/rpc.h> 48 #include <rpc/nettype.h> 49 #include <sys/poll.h> 50 #include <netdir.h> 51 #ifdef PORTMAP 52 #include <rpc/pmap_prot.h> 53 #include <rpc/pmap_clnt.h> 54 #include <rpc/pmap_rmt.h> 55 #endif 56 #ifdef RPC_DEBUG 57 #include <stdio.h> 58 #endif 59 #include <errno.h> 60 #include <syslog.h> 61 #include <stdlib.h> 62 #include <unistd.h> 63 #include <sys/types.h> 64 #include <sys/socket.h> 65 #include <netinet/in.h> 66 #include <arpa/inet.h> 67 68 #define MAXBCAST 20 /* Max no of broadcasting transports */ 69 #define INITTIME 4000 /* Time to wait initially */ 70 #define WAITTIME 8000 /* Maximum time to wait */ 71 72 int lowvers = 1; /* by default, broadcast only version 2 over UDP */ 73 #ifndef NETIDLEN 74 #define NETIDLEN 32 75 #endif 76 77 /* 78 * If nettype is NULL, it broadcasts on all the available 79 * datagram_n transports. May potentially lead to broadacst storms 80 * and hence should be used with caution, care and courage. 81 * 82 * The current parameter xdr packet size is limited by the max tsdu 83 * size of the transport. If the max tsdu size of any transport is 84 * smaller than the parameter xdr packet, then broadcast is not 85 * sent on that transport. 86 * 87 * Also, the packet size should be less the packet size of 88 * the data link layer (for ethernet it is 1400 bytes). There is 89 * no easy way to find out the max size of the data link layer and 90 * we are assuming that the args would be smaller than that. 91 * 92 * The result size has to be smaller than the transport tsdu size. 93 * 94 * If PORTMAP has been defined, we send two packets for UDP, one for 95 * rpcbind and one for portmap. For those machines which support 96 * both rpcbind and portmap, it will cause them to reply twice, and 97 * also here it will get two responses ... inefficient and clumsy. 98 */ 99 100 101 enum clnt_stat 102 rpc_broadcast_exp(const rpcprog_t prog, const rpcvers_t vers, 103 const rpcproc_t proc, const xdrproc_t xargs, caddr_t argsp, 104 const xdrproc_t xresults, caddr_t resultsp, const resultproc_t eachresult, 105 const int inittime, const int waittime, const char *netclass) 106 { 107 enum clnt_stat stat = RPC_SUCCESS; /* Return status */ 108 XDR xdr_stream; /* XDR stream */ 109 XDR *xdrs = &xdr_stream; 110 struct rpc_msg msg; /* RPC message */ 111 struct timeval t; 112 char *outbuf = NULL; /* Broadcast msg buffer */ 113 char *inbuf = NULL; /* Reply buf */ 114 uint_t maxbufsize = 0; 115 AUTH *sys_auth = authsys_create_default(); 116 int i, j; 117 void *handle; 118 char uaddress[1024]; /* A self imposed limit */ 119 char *uaddrp = uaddress; 120 int pmap_reply_flag; /* reply recvd from PORTMAP */ 121 /* An array of all the suitable broadcast transports */ 122 struct { 123 int fd; /* File descriptor */ 124 bool_t udp_flag; /* this is udp */ 125 struct netconfig *nconf; /* Netconfig structure */ 126 uint_t asize; /* Size of the addr buf */ 127 uint_t dsize; /* Size of the data buf */ 128 struct netbuf raddr; /* Remote address */ 129 struct nd_addrlist *nal; /* Broadcast addrs */ 130 } fdlist[MAXBCAST]; 131 struct pollfd pfd[MAXBCAST]; 132 int fdlistno = 0; 133 struct r_rpcb_rmtcallargs barg; /* Remote arguments */ 134 struct r_rpcb_rmtcallres bres; /* Remote results */ 135 struct t_unitdata t_udata, t_rdata; 136 struct netconfig *nconf; 137 struct nd_hostserv hs; 138 int msec; 139 int pollretval; 140 int fds_found; 141 char nettype_array[NETIDLEN]; 142 char *nettype = &nettype_array[0]; 143 144 #ifdef PORTMAP 145 rpcport_t *port; /* Remote port number */ 146 int pmap_flag = 0; /* UDP exists ? */ 147 char *outbuf_pmap = NULL; 148 struct p_rmtcallargs barg_pmap; /* Remote arguments */ 149 struct p_rmtcallres bres_pmap; /* Remote results */ 150 struct t_unitdata t_udata_pmap; 151 int udpbufsz = 0; 152 #endif /* PORTMAP */ 153 154 if (sys_auth == NULL) 155 return (RPC_SYSTEMERROR); 156 /* 157 * initialization: create a fd, a broadcast address, and send the 158 * request on the broadcast transport. 159 * Listen on all of them and on replies, call the user supplied 160 * function. 161 */ 162 163 if (netclass == NULL) 164 nettype = NULL; 165 else { 166 size_t len = strlen(netclass); 167 if (len >= sizeof (nettype_array)) 168 return (RPC_UNKNOWNPROTO); 169 (void) strcpy(nettype, netclass); 170 } 171 172 if (nettype == NULL) 173 nettype = "datagram_n"; 174 if ((handle = __rpc_setconf((char *)nettype)) == NULL) 175 return (RPC_UNKNOWNPROTO); 176 while (nconf = __rpc_getconf(handle)) { 177 struct t_info tinfo; 178 int fd; 179 uint_t addrlen; 180 181 if (nconf->nc_semantics != NC_TPI_CLTS) 182 continue; 183 if (fdlistno >= MAXBCAST) 184 break; /* No more slots available */ 185 if ((fd = t_open(nconf->nc_device, O_RDWR, &tinfo)) == -1) { 186 stat = RPC_CANTSEND; 187 continue; 188 } 189 if (t_bind(fd, NULL, NULL) == -1) { 190 (void) t_close(fd); 191 stat = RPC_CANTSEND; 192 continue; 193 } 194 /* Do protocol specific negotiating for broadcast */ 195 if (netdir_options(nconf, ND_SET_BROADCAST, fd, NULL)) { 196 (void) t_close(fd); 197 stat = RPC_NOBROADCAST; 198 continue; 199 } 200 fdlist[fdlistno].fd = fd; 201 fdlist[fdlistno].nconf = nconf; 202 fdlist[fdlistno].udp_flag = FALSE; 203 if (((addrlen = __rpc_get_a_size(tinfo.addr)) == 0) || 204 ((fdlist[fdlistno].raddr.buf = malloc(addrlen)) == NULL)) { 205 (void) t_close(fd); 206 stat = RPC_SYSTEMERROR; 207 goto done_broad; 208 } 209 fdlist[fdlistno].raddr.maxlen = addrlen; 210 fdlist[fdlistno].raddr.len = addrlen; 211 pfd[fdlistno].events = POLLIN | POLLPRI | 212 POLLRDNORM | POLLRDBAND; 213 pfd[fdlistno].fd = fdlist[fdlistno].fd = fd; 214 fdlist[fdlistno].asize = addrlen; 215 216 if ((fdlist[fdlistno].dsize = __rpc_get_t_size(0, 217 tinfo.tsdu)) == 0) { 218 (void) t_close(fd); 219 free(fdlist[fdlistno].raddr.buf); 220 stat = RPC_SYSTEMERROR; /* XXX */ 221 goto done_broad; 222 } 223 224 if (maxbufsize <= fdlist[fdlistno].dsize) 225 maxbufsize = fdlist[fdlistno].dsize; 226 #ifdef PORTMAP 227 if (strcmp(nconf->nc_protofmly, NC_INET) == 0 && 228 strcmp(nconf->nc_proto, NC_UDP) == 0) { 229 udpbufsz = fdlist[fdlistno].dsize; 230 if ((outbuf_pmap = malloc(udpbufsz)) == NULL) { 231 (void) t_close(fd); 232 free(fdlist[fdlistno].raddr.buf); 233 stat = RPC_SYSTEMERROR; 234 goto done_broad; 235 } 236 pmap_flag = 1; 237 fdlist[fdlistno].udp_flag = TRUE; 238 } 239 #endif 240 fdlistno++; 241 } 242 243 if (fdlistno == 0) { 244 if (stat == RPC_SUCCESS) 245 stat = RPC_UNKNOWNPROTO; 246 goto done_broad; 247 } 248 if (maxbufsize == 0) { 249 if (stat == RPC_SUCCESS) 250 stat = RPC_CANTSEND; 251 goto done_broad; 252 } 253 inbuf = malloc((size_t)maxbufsize); 254 outbuf = malloc((size_t)maxbufsize); 255 if ((inbuf == NULL) || (outbuf == NULL)) { 256 stat = RPC_SYSTEMERROR; 257 goto done_broad; 258 } 259 260 /* Serialize all the arguments which have to be sent */ 261 (void) gettimeofday(&t, (struct timezone *)0); 262 msg.rm_xid = getpid() ^ t.tv_sec ^ t.tv_usec; 263 msg.rm_direction = CALL; 264 msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 265 msg.rm_call.cb_prog = RPCBPROG; 266 msg.rm_call.cb_vers = RPCBVERS; 267 msg.rm_call.cb_proc = RPCBPROC_CALLIT; 268 barg.prog = prog; 269 barg.vers = vers; 270 barg.proc = proc; 271 barg.args.args_val = argsp; 272 barg.xdr_args = xargs; 273 bres.addr = uaddrp; 274 bres.results.results_val = resultsp; 275 bres.xdr_res = xresults; 276 msg.rm_call.cb_cred = sys_auth->ah_cred; 277 msg.rm_call.cb_verf = sys_auth->ah_verf; 278 xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE); 279 if ((!xdr_callmsg(xdrs, &msg)) || 280 (!xdr_rpcb_rmtcallargs(xdrs, &barg))) { 281 stat = RPC_CANTENCODEARGS; 282 goto done_broad; 283 } 284 t_udata.opt.len = 0; 285 t_udata.udata.buf = outbuf; 286 t_udata.udata.len = xdr_getpos(xdrs); 287 t_udata.udata.maxlen = t_udata.udata.len; 288 /* XXX Should have set opt to its legal maxlen. */ 289 t_rdata.opt.len = t_rdata.opt.maxlen = 0; 290 xdr_destroy(xdrs); 291 292 #ifdef PORTMAP 293 /* Prepare the packet for version 2 PORTMAP */ 294 if (pmap_flag) { 295 msg.rm_xid++; /* One way to distinguish */ 296 msg.rm_call.cb_prog = PMAPPROG; 297 msg.rm_call.cb_vers = PMAPVERS; 298 msg.rm_call.cb_proc = PMAPPROC_CALLIT; 299 barg_pmap.prog = prog; 300 barg_pmap.vers = vers; 301 barg_pmap.proc = proc; 302 barg_pmap.args.args_val = argsp; 303 barg_pmap.xdr_args = xargs; 304 port = &bres_pmap.port; /* for use later on */ 305 bres_pmap.xdr_res = xresults; 306 bres_pmap.res.res_val = resultsp; 307 xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE); 308 if ((!xdr_callmsg(xdrs, &msg)) || 309 (!xdr_rmtcallargs(xdrs, &barg_pmap))) { 310 stat = RPC_CANTENCODEARGS; 311 goto done_broad; 312 } 313 t_udata_pmap.opt.len = 0; 314 t_udata_pmap.udata.buf = outbuf_pmap; 315 t_udata_pmap.udata.len = xdr_getpos(xdrs); 316 xdr_destroy(xdrs); 317 } 318 #endif /* PORTMAP */ 319 320 /* 321 * Basic loop: broadcast the packets to transports which 322 * support data packets of size such that one can encode 323 * all the arguments. 324 * Wait a while for response(s). 325 * The response timeout grows larger per iteration. 326 */ 327 hs.h_host = HOST_BROADCAST; 328 hs.h_serv = "rpcbind"; 329 330 for (msec = inittime; msec <= waittime; msec += msec) { 331 /* Broadcast all the packets now */ 332 for (i = 0; i < fdlistno; i++) { 333 if (strcmp(fdlist[i].nconf->nc_protofmly, 334 NC_INET6) == 0) { 335 /* if it's IPv6 */ 336 337 struct netbuf addr; 338 struct sockaddr_in6 sa6; 339 340 /* fill in the multicast address */ 341 bzero((char *)&sa6, sizeof (sa6)); 342 sa6.sin6_family = AF_INET6; 343 sa6.sin6_port = htons(PMAPPORT); 344 (void) inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, 345 &sa6.sin6_addr); 346 addr.maxlen = sizeof (struct sockaddr_in6); 347 addr.len = addr.maxlen; 348 addr.buf = (char *)&sa6; 349 350 /* now send rpcbind message */ 351 t_udata.addr = addr; 352 353 354 if (t_sndudata(fdlist[i].fd, 355 &t_udata)) { 356 (void) syslog(LOG_ERR, 357 "Cannot send broadcast\ 358 packet: %m"); 359 #ifdef RPC_DEBUG 360 t_error("rpc_broadcast: t_sndudata"); 361 #endif 362 stat = RPC_CANTSEND; 363 continue; 364 } 365 366 } else { 367 368 struct nd_addrlist *addrlist; 369 370 if (fdlist[i].dsize < t_udata.udata.len) { 371 stat = RPC_CANTSEND; 372 continue; 373 } 374 if (netdir_getbyname(fdlist[i].nconf, &hs, 375 &addrlist) || (addrlist->n_cnt == 0)) { 376 stat = RPC_N2AXLATEFAILURE; 377 continue; 378 } 379 380 for (j = 0; j < addrlist->n_cnt; j++) { 381 #ifdef RPC_DEBUG 382 struct netconfig *nconf = 383 fdlist[i].nconf; 384 #endif 385 386 t_udata.addr = addrlist->n_addrs[j]; 387 388 /* 389 * Only use version 3 if lowvers 390 * is not set or transport is not UDP. 391 */ 392 393 if (!lowvers || !fdlist[i].udp_flag) 394 if (t_sndudata(fdlist[i].fd, 395 &t_udata)) { 396 (void) syslog(LOG_ERR, 397 "Cannot send broadcast\ 398 packet: %m"); 399 #ifdef RPC_DEBUG 400 t_error("rpc_broadcast: t_sndudata"); 401 #endif 402 stat = RPC_CANTSEND; 403 continue; 404 }; 405 #ifdef RPC_DEBUG 406 if (!lowvers || !fdlist[i].udp_flag) 407 fprintf(stderr, "Broadcast\ 408 packet sent for %s\n", nconf->nc_netid); 409 #endif 410 #ifdef PORTMAP 411 /* 412 * Send the version 2 packet also 413 * for UDP/IP 414 */ 415 if (fdlist[i].udp_flag) { 416 t_udata_pmap.addr = 417 t_udata.addr; 418 if (t_sndudata(fdlist[i].fd, 419 &t_udata_pmap)) { 420 (void) syslog(LOG_ERR,\ 421 "Cannot send broadcast packet: %m"); 422 #ifdef RPC_DEBUG 423 t_error("rpc_broadcast:\ 424 t_sndudata"); 425 #endif 426 stat = RPC_CANTSEND; 427 continue; 428 } 429 } 430 #ifdef RPC_DEBUG 431 fprintf(stderr, "PMAP Broadcast packet\ 432 sent for %s\n", nconf->nc_netid); 433 #endif 434 #endif /* PORTMAP */ 435 } 436 /* End for sending all packets on this transport */ 437 (void) netdir_free((char *)addrlist, ND_ADDRLIST); 438 } /* end non-IPv6 */ 439 440 } /* End for sending on all transports */ 441 442 if (eachresult == NULL) { 443 stat = RPC_SUCCESS; 444 goto done_broad; 445 } 446 447 /* 448 * Get all the replies from these broadcast requests 449 */ 450 recv_again: 451 452 switch (pollretval = poll(pfd, fdlistno, msec)) { 453 case 0: /* timed out */ 454 stat = RPC_TIMEDOUT; 455 continue; 456 case -1: /* some kind of error - we ignore it */ 457 goto recv_again; 458 } /* end of poll results switch */ 459 460 t_rdata.udata.buf = inbuf; 461 462 for (i = fds_found = 0; 463 i < fdlistno && fds_found < pollretval; i++) { 464 465 int flag; 466 bool_t done = FALSE; 467 468 if (pfd[i].revents == 0) 469 continue; 470 else if (pfd[i].revents & POLLNVAL) { 471 /* 472 * Something bad has happened to this descri- 473 * ptor. We can cause poll() to ignore 474 * it simply by using a negative fd. We do that 475 * rather than compacting the pfd[] and fdlist[] 476 * arrays. 477 */ 478 pfd[i].fd = -1; 479 fds_found++; 480 continue; 481 } else 482 fds_found++; 483 #ifdef RPC_DEBUG 484 fprintf(stderr, "response for %s\n", 485 fdlist[i].nconf->nc_netid); 486 #endif 487 try_again: 488 t_rdata.udata.maxlen = fdlist[i].dsize; 489 t_rdata.udata.len = 0; 490 t_rdata.addr = fdlist[i].raddr; 491 if (t_rcvudata(fdlist[i].fd, &t_rdata, &flag) == -1) { 492 if (t_errno == TSYSERR && errno == EINTR) 493 goto try_again; 494 495 /* 496 * Ignore any T_UDERR look errors. 497 * We should never see any ICMP port 498 * unreachables when broadcasting but it has 499 * been observed with broken IP 500 * implementations. 501 */ 502 if (t_errno == TLOOK && 503 t_look(fdlist[i].fd) == T_UDERR && 504 t_rcvuderr(fdlist[i].fd, NULL) == 0) 505 goto recv_again; 506 507 (void) syslog(LOG_ERR, 508 "Cannot receive reply to \ 509 broadcast: %m"); 510 stat = RPC_CANTRECV; 511 continue; 512 } 513 /* 514 * Not taking care of flag for T_MORE. 515 * We are assuming that 516 * such calls should not take more than one 517 * transport packet. 518 */ 519 if (flag & T_MORE) 520 continue; /* Drop that and go ahead */ 521 if (t_rdata.udata.len < (uint_t)sizeof (uint32_t)) 522 continue; /* Drop that and go ahead */ 523 /* 524 * see if reply transaction id matches sent id. 525 * If so, decode the results. If return id is xid + 1 526 * it was a PORTMAP reply 527 */ 528 /* LINTED pointer cast */ 529 if (*((uint32_t *)(inbuf)) == *((uint32_t *)(outbuf))) { 530 pmap_reply_flag = 0; 531 msg.acpted_rply.ar_verf = _null_auth; 532 msg.acpted_rply.ar_results.where = 533 (caddr_t)&bres; 534 msg.acpted_rply.ar_results.proc = 535 (xdrproc_t)xdr_rpcb_rmtcallres; 536 #ifdef PORTMAP 537 } else if (pmap_flag && 538 /* LINTED pointer cast */ 539 *((uint32_t *)(inbuf)) == 540 /* LINTED pointer cast */ 541 *((uint32_t *)(outbuf_pmap))) { 542 pmap_reply_flag = 1; 543 msg.acpted_rply.ar_verf = _null_auth; 544 msg.acpted_rply.ar_results.where = 545 (caddr_t)&bres_pmap; 546 msg.acpted_rply.ar_results.proc = 547 (xdrproc_t)xdr_rmtcallres; 548 #endif /* PORTMAP */ 549 } else 550 continue; 551 xdrmem_create(xdrs, inbuf, 552 (uint_t)t_rdata.udata.len, XDR_DECODE); 553 if (xdr_replymsg(xdrs, &msg)) { 554 if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && 555 (msg.acpted_rply.ar_stat == SUCCESS)) { 556 struct netbuf *taddr; 557 #ifdef PORTMAP 558 if (pmap_flag && pmap_reply_flag) { 559 /* convert port to taddr */ 560 /* LINTED pointer cast */ 561 ((struct sockaddr_in *) 562 t_rdata.addr.buf)->sin_port = 563 htons((ushort_t)*port); 564 taddr = &t_rdata.addr; 565 } else /* Convert the uaddr to taddr */ 566 #endif 567 taddr = uaddr2taddr( 568 fdlist[i].nconf, 569 uaddrp); 570 done = (*eachresult)(resultsp, taddr, 571 fdlist[i].nconf); 572 #ifdef RPC_DEBUG 573 { 574 int k; 575 576 printf("rmt addr = "); 577 for (k = 0; k < taddr->len; k++) 578 printf("%d ", taddr->buf[k]); 579 printf("\n"); 580 } 581 #endif 582 if (taddr && !pmap_reply_flag) 583 netdir_free((char *)taddr, 584 ND_ADDR); 585 } 586 /* otherwise, we just ignore the errors ... */ 587 } 588 /* else some kind of deserialization problem ... */ 589 590 xdrs->x_op = XDR_FREE; 591 msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; 592 (void) xdr_replymsg(xdrs, &msg); 593 (void) (*xresults)(xdrs, resultsp); 594 XDR_DESTROY(xdrs); 595 if (done) { 596 stat = RPC_SUCCESS; 597 goto done_broad; 598 } else { 599 if (rpc_callerr.re_status == RPC_SYSTEMERROR) { 600 stat = RPC_SYSTEMERROR; 601 goto done_broad; 602 } 603 goto recv_again; 604 } 605 } /* The recv for loop */ 606 } /* The giant for loop */ 607 608 done_broad: 609 if (inbuf) 610 free(inbuf); 611 if (outbuf) 612 free(outbuf); 613 #ifdef PORTMAP 614 if (outbuf_pmap) 615 free(outbuf_pmap); 616 #endif 617 for (i = 0; i < fdlistno; i++) { 618 (void) t_close(fdlist[i].fd); 619 free(fdlist[i].raddr.buf); 620 } 621 AUTH_DESTROY(sys_auth); 622 (void) __rpc_endconf(handle); 623 624 return (stat); 625 } 626 627 enum clnt_stat 628 rpc_broadcast(const rpcprog_t prog, const rpcvers_t vers, const rpcproc_t proc, 629 const xdrproc_t xargs, caddr_t argsp, xdrproc_t const xresults, 630 caddr_t resultsp, const resultproc_t eachresult, const char *nettype) 631 { 632 return (rpc_broadcast_exp(prog, vers, proc, xargs, argsp, 633 xresults, resultsp, eachresult, 634 INITTIME, WAITTIME, nettype)); 635 } 636