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