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