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
rpc_broadcast_exp(const rpcprog_t prog,const rpcvers_t vers,const rpcproc_t proc,const xdrproc_t xargs,caddr_t argsp,const xdrproc_t xresults,caddr_t resultsp,const resultproc_t eachresult,const int inittime,const int waittime,const char * netclass)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
rpc_broadcast(const rpcprog_t prog,const rpcvers_t vers,const rpcproc_t proc,const xdrproc_t xargs,caddr_t argsp,xdrproc_t const xresults,caddr_t resultsp,const resultproc_t eachresult,const char * nettype)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