Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libc / rpc / PSD.doc / rpc.prog.ms
1 .\"
2 .\" Must use -- tbl and pic -- with this one
3 .\"
4 .\" @(#)rpc.prog.ms     2.3 88/08/11 4.0 RPCSRC
5 .\" $FreeBSD: src/lib/libc/rpc/PSD.doc/rpc.prog.ms,v 1.1.14.1 2000/11/24 09:36:30 ru Exp $
6 .\"
7 .so stubs
8 .de BT
9 .if \\n%=1 .tl ''- % -''
10 ..
11 .nr OF 0
12 .ND
13 .\" prevent excess underlining in nroff
14 .if n .fp 2 R
15 .OH 'Remote Procedure Call Programming Guide''Page %'
16 .EH 'Page %''Remote Procedure Call Programming Guide'
17 .SH
18 \&Remote Procedure Call Programming Guide
19 .nr OF 1
20 .IX "Network Programming" "" "" "" PAGE MAJOR
21 .IX "RPC Programming Guide"
22 .LP
23 This document assumes a working knowledge of network theory.  It is
24 intended for programmers who wish to write network applications using
25 remote procedure calls (explained below), and who want to understand
26 the RPC mechanisms usually hidden by the
27 .I rpcgen(1) 
28 protocol compiler.
29 .I rpcgen 
30 is described in detail in the previous chapter, the
31 .I "\fBrpcgen\fP \fIProgramming Guide\fP".
32 .SH
33 Note:
34 .I
35 .IX rpcgen "" \fIrpcgen\fP
36 Before attempting to write a network application, or to convert an
37 existing non-network application to run over the network, you may want to
38 understand the material in this chapter.  However, for most applications,
39 you can circumvent the need to cope with the details presented here by using
40 .I rpcgen .
41 The
42 .I "Generating XDR Routines"
43 section of that chapter contains the complete source for a working RPC
44 service\(ema remote directory listing service which uses
45 .I rpcgen 
46 to generate XDR routines as well as client and server stubs.
47 .LP
48 .LP
49 What are remote procedure calls?  Simply put, they are the high-level
50 communications paradigm used in the operating system.
51 RPC presumes the existence of
52 low-level networking mechanisms (such as TCP/IP and UDP/IP), and upon them
53 it implements a logical client to server communications system designed
54 specifically for the support of network applications.  With RPC, the client
55 makes a procedure call to send a data packet to the server.  When the
56 packet arrives, the server calls a dispatch routine, performs whatever
57 service is requested, sends back the reply, and the procedure call returns
58 to the client.
59 .NH 0
60 \&Layers of RPC
61 .IX "layers of RPC"
62 .IX "RPC" "layers"
63 .LP
64 The RPC interface can be seen as being divided into three layers.\**
65 .FS
66 For a complete specification of the routines in the remote procedure
67 call Library, see the
68 .I rpc(3N) 
69 manual page.
70 .FE
71 .LP
72 .I "The Highest Layer:"
73 .IX RPC "The Highest Layer"
74 The highest layer is totally transparent to the operating system, 
75 machine and network upon which is is run.  It's probably best to 
76 think of this level as a way of
77 .I using
78 RPC, rather than as
79 a \fIpart of\fP RPC proper.  Programmers who write RPC routines 
80 should (almost) always make this layer available to others by way 
81 of a simple C front end that entirely hides the networking.
82 .LP 
83 To illustrate, at this level a program can simply make a call to
84 .I rnusers (),
85 a C routine which returns the number of users on a remote machine.
86 The user is not explicitly aware of using RPC \(em they simply 
87 call a procedure, just as they would call
88 .I malloc() .
89 .LP
90 .I "The Middle Layer:"
91 .IX RPC "The Middle Layer"
92 The middle layer is really \*QRPC proper.\*U  Here, the user doesn't
93 need to consider details about sockets, the UNIX system, or other low-level 
94 implementation mechanisms.  They simply make remote procedure calls
95 to routines on other machines.  The selling point here is simplicity.  
96 It's this layer that allows RPC to pass the \*Qhello world\*U test \(em
97 simple things should be simple.  The middle-layer routines are used 
98 for most applications.
99 .LP
100 RPC calls are made with the system routines
101 .I registerrpc()
102 .I callrpc()
103 and
104 .I svc_run ().
105 The first two of these are the most fundamental:
106 .I registerrpc() 
107 obtains a unique system-wide procedure-identification number, and
108 .I callrpc() 
109 actually executes a remote procedure call.  At the middle level, a 
110 call to 
111 .I rnusers()
112 is implemented by way of these two routines.
113 .LP
114 The middle layer is unfortunately rarely used in serious programming 
115 due to its inflexibility (simplicity).  It does not allow timeout 
116 specifications or the choice of transport.  It allows no UNIX
117 process control or flexibility in case of errors.  It doesn't support
118 multiple kinds of call authentication.  The programmer rarely needs 
119 all these kinds of control, but one or two of them is often necessary.
120 .LP
121 .I "The Lowest Layer:"
122 .IX RPC "The Lowest Layer"
123 The lowest layer does allow these details to be controlled by the 
124 programmer, and for that reason it is often necessary.  Programs 
125 written at this level are also most efficient, but this is rarely a
126 real issue \(em since RPC clients and servers rarely generate 
127 heavy network loads.
128 .LP
129 Although this document only discusses the interface to C,
130 remote procedure calls can be made from any language.
131 Even though this document discusses RPC
132 when it is used to communicate
133 between processes on different machines,
134 it works just as well for communication
135 between different processes on the same machine.
136 .br
137 .KS
138 .NH 2
139 \&The RPC Paradigm
140 .IX RPC paradigm
141 .LP
142 Here is a diagram of the RPC paradigm:
143 .LP
144 \fBFigure 1-1\fI Network Communication with the Remote Reocedure Call\fR
145 .LP
146 .PS
147 L1: arrow down 1i "client " rjust "program " rjust
148 L2: line right 1.5i "\fIcallrpc\fP" "function"
149 move up 1.5i; line dotted down 6i; move up 4.5i
150 arrow right 1i
151 L3: arrow down 1i "invoke " rjust "service " rjust
152 L4: arrow right 1.5i "call" "service"
153 L5: arrow down 1i " service" ljust " executes" ljust
154 L6: arrow left 1.5i "\fIreturn\fP" "answer"
155 L7: arrow down 1i "request " rjust "completed " rjust
156 L8: line left 1i
157 arrow left 1.5i "\fIreturn\fP" "reply"
158 L9: arrow down 1i "program " rjust "continues " rjust
159 line dashed down from L2 to L9
160 line dashed down from L4 to L7
161 line dashed up 1i from L3 "service " rjust "daemon " rjust
162 arrow dashed down 1i from L8
163 move right 1i from L3
164 box invis "Machine B"
165 move left 1.2i from L2; move down
166 box invis "Machine A"
167 .PE
168 .KE
169 .KS
170 .NH 1
171 \&Higher Layers of RPC
172 .NH 2
173 \&Highest Layer
174 .IX "highest layer of RPC"
175 .IX RPC "highest layer"
176 .LP
177 Imagine you're writing a program that needs to know
178 how many users are logged into a remote machine.
179 You can do this by calling the RPC library routine
180 .I rnusers()
181 as illustrated below:
182 .ie t .DS
183 .el .DS L
184 .ft CW
185 #include <stdio.h>
186
187 main(argc, argv)
188         int argc;
189         char **argv;
190 {
191         int num;
192
193         if (argc != 2) {
194                 fprintf(stderr, "usage: rnusers hostname\en");
195                 exit(1);
196         }
197         if ((num = rnusers(argv[1])) < 0) {
198                 fprintf(stderr, "error: rnusers\en");
199                 exit(-1);
200         }
201         printf("%d users on %s\en", num, argv[1]);
202         exit(0);
203 }
204 .DE
205 .KE
206 RPC library routines such as
207 .I rnusers() 
208 are in the RPC services library
209 .I librpcsvc.a
210 Thus, the program above should be compiled with
211 .DS
212 .ft CW
213 % cc \fIprogram.c -lrpcsvc\fP
214 .DE
215 .I rnusers (),
216 like the other RPC library routines, is documented in section 3R 
217 of the
218 .I "System Interface Manual for the Sun Workstation" ,
219 the same section which documents the standard Sun RPC services.  
220 .IX "RPC Services"
221 See the 
222 .I intro(3R) 
223 manual page for an explanation of the documentation strategy 
224 for these services and their RPC protocols.
225 .LP
226 Here are some of the RPC service library routines available to the 
227 C programmer:
228 .LP
229 \fBTable 3-3\fI RPC Service Library Routines\fR
230 .TS
231 box tab (&) ;
232 cfI cfI
233 lfL l .
234 Routine&Description
235 _
236 .sp .5
237 rnusers&Return number of users on remote machine
238 rusers&Return information about users on remote machine
239 havedisk&Determine if remote machine has disk
240 rstats&Get performance data from remote kernel
241 rwall&Write to specified remote machines
242 yppasswd&Update user password in Yellow Pages
243 .TE
244 .LP
245 Other RPC services \(em for example
246 .I ether()
247 .I mount
248 .I rquota()
249 and
250 .I spray
251 \(em are not available to the C programmer as library routines.
252 They do, however,
253 have RPC program numbers so they can be invoked with
254 .I callrpc()
255 which will be discussed in the next section.  Most of them also 
256 have compilable 
257 .I rpcgen(1) 
258 protocol description files.  (The
259 .I rpcgen
260 protocol compiler radically simplifies the process of developing
261 network applications.  
262 See the \fBrpcgen\fI Programming Guide\fR
263 for detailed information about 
264 .I rpcgen 
265 and 
266 .I rpcgen 
267 protocol description files).
268 .KS
269 .NH 2
270 \&Intermediate Layer
271 .IX "intermediate layer of RPC"
272 .IX "RPC" "intermediate layer"
273 .LP
274 The simplest interface, which explicitly makes RPC calls, uses the 
275 functions
276 .I callrpc()
277 and
278 .I registerrpc()
279 Using this method, the number of remote users can be gotten as follows:
280 .ie t .DS
281 .el .DS L
282 #include <stdio.h>
283 #include <rpc/rpc.h>
284 #include <utmp.h>
285 #include <rpcsvc/rusers.h>
286
287 main(argc, argv)
288         int argc;
289         char **argv;
290 {
291         unsigned long nusers;
292         int stat;
293
294         if (argc != 2) {
295                 fprintf(stderr, "usage: nusers hostname\en");
296                 exit(-1);
297         }
298         if (stat = callrpc(argv[1],
299           RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
300           xdr_void, 0, xdr_u_long, &nusers) != 0) {
301                 clnt_perrno(stat);
302                 exit(1);
303         }
304         printf("%d users on %s\en", nusers, argv[1]);
305         exit(0);
306 }
307 .DE
308 .KE
309 Each RPC procedure is uniquely defined by a program number, 
310 version number, and procedure number.  The program number 
311 specifies a group of related remote procedures, each of 
312 which has a different procedure number.  Each program also 
313 has a version number, so when a minor change is made to a 
314 remote service (adding a new procedure, for example), a new 
315 program number doesn't have to be assigned.  When you want 
316 to call a procedure to find the number of remote users, you 
317 look up the appropriate program, version and procedure numbers
318 in a manual, just as you look up the name of a memory allocator 
319 when you want to allocate memory.
320 .LP
321 The simplest way of making remote procedure calls is with the the RPC 
322 library routine
323 .I callrpc()
324 It has eight parameters.  The first is the name of the remote server 
325 machine.  The next three parameters are the program, version, and procedure 
326 numbers\(emtogether they identify the procedure to be called.
327 The fifth and sixth parameters are an XDR filter and an argument to
328 be encoded and passed to the remote procedure.  
329 The final two parameters are a filter for decoding the results 
330 returned by the remote procedure and a pointer to the place where 
331 the procedure's results are to be stored.  Multiple arguments and
332 results are handled by embedding them in structures.  If 
333 .I callrpc() 
334 completes successfully, it returns zero; else it returns a nonzero 
335 value.  The return codes (of type
336 .IX "enum clnt_stat (in RPC programming)" "" "\fIenum clnt_stat\fP (in RPC programming)"
337 cast into an integer) are found in 
338 .I <rpc/clnt.h> .
339 .LP
340 Since data types may be represented differently on different machines,
341 .I callrpc() 
342 needs both the type of the RPC argument, as well as
343 a pointer to the argument itself (and similarly for the result).  For
344 .I RUSERSPROC_NUM ,
345 the return value is an
346 .I "unsigned long"
347 so
348 .I callrpc() 
349 has
350 .I xdr_u_long() 
351 as its first return parameter, which says
352 that the result is of type
353 .I "unsigned long"
354 and
355 .I &nusers 
356 as its second return parameter,
357 which is a pointer to where the long result will be placed.  Since
358 .I RUSERSPROC_NUM 
359 takes no argument, the argument parameter of
360 .I callrpc() 
361 is
362 .I xdr_void ().
363 .LP
364 After trying several times to deliver a message, if
365 .I callrpc() 
366 gets no answer, it returns with an error code.
367 The delivery mechanism is UDP,
368 which stands for User Datagram Protocol.
369 Methods for adjusting the number of retries
370 or for using a different protocol require you to use the lower
371 layer of the RPC library, discussed later in this document.
372 The remote server procedure
373 corresponding to the above might look like this:
374 .ie t .DS
375 .el .DS L
376 .ft CW
377 .ft CW
378 char *
379 nuser(indata)
380         char *indata;
381 {
382         unsigned long nusers;
383
384 .ft I
385         /*
386          * Code here to compute the number of users
387          * and place result in variable \fInusers\fP.
388          */
389 .ft CW
390         return((char *)&nusers);
391 }
392 .DE
393 .LP
394 It takes one argument, which is a pointer to the input
395 of the remote procedure call (ignored in our example),
396 and it returns a pointer to the result.
397 In the current version of C,
398 character pointers are the generic pointers,
399 so both the input argument and the return value are cast to
400 .I "char *" .
401 .LP
402 Normally, a server registers all of the RPC calls it plans
403 to handle, and then goes into an infinite loop waiting to service requests.
404 In this example, there is only a single procedure
405 to register, so the main body of the server would look like this:
406 .ie t .DS
407 .el .DS L
408 .ft CW
409 #include <stdio.h>
410 #include <rpc/rpc.h>
411 #include <utmp.h>
412 #include <rpcsvc/rusers.h>
413
414 char *nuser();
415
416 main()
417 {
418         registerrpc(RUSERSPROG, RUSERSVERS, RUSERSPROC_NUM,
419                 nuser, xdr_void, xdr_u_long);
420         svc_run();              /* \fINever returns\fP */
421         fprintf(stderr, "Error: svc_run returned!\en");
422         exit(1);
423 }
424 .DE
425 .LP
426 The
427 .I registerrpc()
428 routine registers a C procedure as corresponding to a
429 given RPC procedure number.  The first three parameters,
430 .I RUSERPROG ,
431 .I RUSERSVERS ,
432 and
433 .I RUSERSPROC_NUM 
434 are the program, version, and procedure numbers
435 of the remote procedure to be registered;
436 .I nuser() 
437 is the name of the local procedure that implements the remote
438 procedure; and
439 .I xdr_void() 
440 and
441 .I xdr_u_long() 
442 are the XDR filters for the remote procedure's arguments and
443 results, respectively.  (Multiple arguments or multiple results
444 are passed as structures).
445 .LP
446 Only the UDP transport mechanism can use
447 .I registerrpc()
448 thus, it is always safe in conjunction with calls generated by
449 .I callrpc() .
450 .SH
451 .IX "UDP 8K warning"
452 Warning: the UDP transport mechanism can only deal with
453 arguments and results less than 8K bytes in length.
454 .LP
455 .LP
456 After registering the local procedure, the server program's
457 main procedure calls
458 .I svc_run (),
459 the RPC library's remote procedure dispatcher.  It is this 
460 function that calls the remote procedures in response to RPC
461 call messages.  Note that the dispatcher takes care of decoding
462 remote procedure arguments and encoding results, using the XDR
463 filters specified when the remote procedure was registered.
464 .NH 2
465 \&Assigning Program Numbers
466 .IX "program number assignment"
467 .IX "assigning program numbers"
468 .LP
469 Program numbers are assigned in groups of 
470 .I 0x20000000 
471 according to the following chart:
472 .DS
473 .ft CW
474        0x0 - 0x1fffffff \fRDefined by Sun\fP
475 0x20000000 - 0x3fffffff \fRDefined by user\fP
476 0x40000000 - 0x5fffffff \fRTransient\fP
477 0x60000000 - 0x7fffffff \fRReserved\fP
478 0x80000000 - 0x9fffffff \fRReserved\fP
479 0xa0000000 - 0xbfffffff \fRReserved\fP
480 0xc0000000 - 0xdfffffff \fRReserved\fP
481 0xe0000000 - 0xffffffff \fRReserved\fP
482 .ft R
483 .DE
484 Sun Microsystems administers the first group of numbers, which
485 should be identical for all Sun customers.  If a customer
486 develops an application that might be of general interest, that
487 application should be given an assigned number in the first
488 range.  The second group of numbers is reserved for specific
489 customer applications.  This range is intended primarily for
490 debugging new programs.  The third group is reserved for
491 applications that generate program numbers dynamically.  The
492 final groups are reserved for future use, and should not be
493 used.
494 .LP
495 To register a protocol specification, send a request by network 
496 mail to
497 .I rpc@sun
498 or write to:
499 .DS
500 RPC Administrator
501 Sun Microsystems
502 2550 Garcia Ave.
503 Mountain View, CA 94043
504 .DE
505 Please include a compilable 
506 .I rpcgen 
507 \*Q.x\*U file describing your protocol.
508 You will be given a unique program number in return.
509 .IX RPC administration
510 .IX administration "of RPC"
511 .LP
512 The RPC program numbers and protocol specifications 
513 of standard Sun RPC services can be
514 found in the include files in 
515 .I "/usr/include/rpcsvc" .
516 These services, however, constitute only a small subset 
517 of those which have been registered.  The complete list of 
518 registered programs, as of the time when this manual was 
519 printed, is:
520 .LP
521 \fBTable 3-2\fI RPC Registered Programs\fR
522 .TS H
523 box tab (&) ;
524 lfBI lfBI lfBI
525 lfL lfL lfI .
526 RPC Number&Program&Description
527 _
528 .TH
529 .sp .5
530 100000&PMAPPROG&portmapper
531 100001&RSTATPROG&remote stats            
532 100002&RUSERSPROG&remote users            
533 100003&NFSPROG&nfs                     
534 100004&YPPROG&Yellow Pages            
535 100005&MOUNTPROG&mount demon             
536 100006&DBXPROG&remote dbx              
537 100007&YPBINDPROG&yp binder               
538 100008&WALLPROG&shutdown msg            
539 100009&YPPASSWDPROG&yppasswd server         
540 100010&ETHERSTATPROG&ether stats             
541 100011&RQUOTAPROG&disk quotas             
542 100012&SPRAYPROG&spray packets           
543 100013&IBM3270PROG&3270 mapper             
544 100014&IBMRJEPROG&RJE mapper              
545 100015&SELNSVCPROG&selection service       
546 100016&RDATABASEPROG&remote database access  
547 100017&REXECPROG&remote execution        
548 100018&ALICEPROG&Alice Office Automation 
549 100019&SCHEDPROG&scheduling service      
550 100020&LOCKPROG&local lock manager      
551 100021&NETLOCKPROG&network lock manager    
552 100022&X25PROG&x.25 inr protocol       
553 100023&STATMON1PROG&status monitor 1        
554 100024&STATMON2PROG&status monitor 2        
555 100025&SELNLIBPROG&selection library       
556 100026&BOOTPARAMPROG&boot parameters service 
557 100027&MAZEPROG&mazewars game           
558 100028&YPUPDATEPROG&yp update               
559 100029&KEYSERVEPROG&key server              
560 100030&SECURECMDPROG&secure login            
561 100031&NETFWDIPROG&nfs net forwarder init       
562 100032&NETFWDTPROG&nfs net forwarder trans      
563 100033&SUNLINKMAP_PROG&sunlink MAP              
564 100034&NETMONPROG&network monitor               
565 100035&DBASEPROG&lightweight database   
566 100036&PWDAUTHPROG&password authorization       
567 100037&TFSPROG&translucent file svc     
568 100038&NSEPROG&nse server               
569 100039&NSE_ACTIVATE_PROG&nse activate daemon    
570 .sp .2i
571 150001&PCNFSDPROG&pc passwd authorization 
572 .sp .2i
573 200000&PYRAMIDLOCKINGPROG&Pyramid-locking         
574 200001&PYRAMIDSYS5&Pyramid-sys5            
575 200002&CADDS_IMAGE&CV cadds_image               
576 .sp .2i
577 300001&ADT_RFLOCKPROG&ADT file locking  
578 .TE
579 .NH 2
580 \&Passing Arbitrary Data Types
581 .IX "arbitrary data types"
582 .LP
583 In the previous example, the RPC call passes a single
584 .I "unsigned long"
585 RPC can handle arbitrary data structures, regardless of
586 different machines' byte orders or structure layout conventions,
587 by always converting them to a network standard called
588 .I "External Data Representation"
589 (XDR) before
590 sending them over the wire.
591 The process of converting from a particular machine representation
592 to XDR format is called
593 .I serializing ,
594 and the reverse process is called
595 .I deserializing .
596 The type field parameters of
597 .I callrpc() 
598 and
599 .I registerrpc() 
600 can be a built-in procedure like
601 .I xdr_u_long() 
602 in the previous example, or a user supplied one.
603 XDR has these built-in type routines:
604 .IX RPC "built-in routines"
605 .DS
606 .ft CW
607 xdr_int()      xdr_u_int()      xdr_enum()
608 xdr_long()     xdr_u_long()     xdr_bool()
609 xdr_short()    xdr_u_short()    xdr_wrapstring()
610 xdr_char()     xdr_u_char()
611 .DE
612 Note that the routine
613 .I xdr_string() 
614 exists, but cannot be used with 
615 .I callrpc() 
616 and
617 .I registerrpc (),
618 which only pass two parameters to their XDR routines.
619 .I xdr_wrapstring() 
620 has only two parameters, and is thus OK.  It calls 
621 .I xdr_string ().
622 .LP
623 As an example of a user-defined type routine,
624 if you wanted to send the structure
625 .DS
626 .ft CW
627 struct simple {
628         int a;
629         short b;
630 } simple;
631 .DE
632 then you would call
633 .I callrpc() 
634 as
635 .DS
636 .ft CW
637 callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
638         xdr_simple, &simple ...);
639 .DE
640 where
641 .I xdr_simple() 
642 is written as:
643 .ie t .DS
644 .el .DS L
645 .ft CW
646 #include <rpc/rpc.h>
647
648 xdr_simple(xdrsp, simplep)
649         XDR *xdrsp;
650         struct simple *simplep;
651 {
652         if (!xdr_int(xdrsp, &simplep->a))
653                 return (0);
654         if (!xdr_short(xdrsp, &simplep->b))
655                 return (0);
656         return (1);
657 }
658 .DE
659 .LP
660 An XDR routine returns nonzero (true in the sense of C) if it 
661 completes successfully, and zero otherwise.
662 A complete description of XDR is in the
663 .I "XDR Protocol Specification" 
664 section of this manual, only few implementation examples are 
665 given here.
666 .LP
667 In addition to the built-in primitives,
668 there are also the prefabricated building blocks:
669 .DS
670 .ft CW
671 xdr_array()       xdr_bytes()     xdr_reference()
672 xdr_vector()      xdr_union()     xdr_pointer()
673 xdr_string()      xdr_opaque()
674 .DE
675 To send a variable array of integers,
676 you might package them up as a structure like this
677 .DS
678 .ft CW
679 struct varintarr {
680         int *data;
681         int arrlnth;
682 } arr;
683 .DE
684 and make an RPC call such as
685 .DS
686 .ft CW
687 callrpc(hostname, PROGNUM, VERSNUM, PROCNUM,
688         xdr_varintarr, &arr...);
689 .DE
690 with
691 .I xdr_varintarr() 
692 defined as:
693 .ie t .DS
694 .el .DS L
695 .ft CW
696 xdr_varintarr(xdrsp, arrp)
697         XDR *xdrsp;
698         struct varintarr *arrp;
699 {
700         return (xdr_array(xdrsp, &arrp->data, &arrp->arrlnth, 
701                 MAXLEN, sizeof(int), xdr_int));
702 }
703 .DE
704 This routine takes as parameters the XDR handle,
705 a pointer to the array, a pointer to the size of the array,
706 the maximum allowable array size,
707 the size of each array element,
708 and an XDR routine for handling each array element.
709 .KS
710 .LP
711 If the size of the array is known in advance, one can use
712 .I xdr_vector (),
713 which serializes fixed-length arrays.
714 .ie t .DS
715 .el .DS L
716 .ft CW
717 int intarr[SIZE];
718
719 xdr_intarr(xdrsp, intarr)
720         XDR *xdrsp;
721         int intarr[];
722 {
723         int i;
724
725         return (xdr_vector(xdrsp, intarr, SIZE, sizeof(int),
726                 xdr_int));
727 }
728 .DE
729 .KE
730 .LP
731 XDR always converts quantities to 4-byte multiples when serializing.
732 Thus, if either of the examples above involved characters
733 instead of integers, each character would occupy 32 bits.
734 That is the reason for the XDR routine
735 .I xdr_bytes()
736 which is like
737 .I xdr_array()
738 except that it packs characters;
739 .I xdr_bytes() 
740 has four parameters, similar to the first four parameters of
741 .I xdr_array ().
742 For null-terminated strings, there is also the
743 .I xdr_string()
744 routine, which is the same as
745 .I xdr_bytes() 
746 without the length parameter.
747 On serializing it gets the string length from
748 .I strlen (),
749 and on deserializing it creates a null-terminated string.
750 .LP
751 Here is a final example that calls the previously written
752 .I xdr_simple() 
753 as well as the built-in functions
754 .I xdr_string() 
755 and
756 .I xdr_reference (),
757 which chases pointers:
758 .ie t .DS
759 .el .DS L
760 .ft CW
761 struct finalexample {
762         char *string;
763         struct simple *simplep;
764 } finalexample;
765
766 xdr_finalexample(xdrsp, finalp)
767         XDR *xdrsp;
768         struct finalexample *finalp;
769 {
770
771         if (!xdr_string(xdrsp, &finalp->string, MAXSTRLEN))
772                 return (0);
773         if (!xdr_reference(xdrsp, &finalp->simplep,
774           sizeof(struct simple), xdr_simple);
775                 return (0);
776         return (1);
777 }
778 .DE
779 Note that we could as easily call
780 .I xdr_simple() 
781 here instead of
782 .I xdr_reference ().
783 .NH 1
784 \&Lowest Layer of RPC
785 .IX "lowest layer of RPC"
786 .IX "RPC" "lowest layer"
787 .LP
788 In the examples given so far,
789 RPC takes care of many details automatically for you.
790 In this section, we'll show you how you can change the defaults
791 by using lower layers of the RPC library.
792 It is assumed that you are familiar with sockets
793 and the system calls for dealing with them.
794 .LP
795 There are several occasions when you may need to use lower layers of 
796 RPC.  First, you may need to use TCP, since the higher layer uses UDP, 
797 which restricts RPC calls to 8K bytes of data.  Using TCP permits calls 
798 to send long streams of data.  
799 For an example, see the
800 .I TCP
801 section below.  Second, you may want to allocate and free memory
802 while serializing or deserializing with XDR routines.  
803 There is no call at the higher level to let 
804 you free memory explicitly.  
805 For more explanation, see the
806 .I "Memory Allocation with XDR"
807 section below.  
808 Third, you may need to perform authentication 
809 on either the client or server side, by supplying 
810 credentials or verifying them.
811 See the explanation in the 
812 .I Authentication
813 section below.
814 .NH 2
815 \&More on the Server Side
816 .IX RPC "server side"
817 .LP
818 The server for the
819 .I nusers() 
820 program shown below does the same thing as the one using
821 .I registerrpc() 
822 above, but is written using a lower layer of the RPC package:
823 .ie t .DS
824 .el .DS L
825 .ft CW
826 #include <stdio.h>
827 #include <rpc/rpc.h>
828 #include <utmp.h>
829 #include <rpcsvc/rusers.h>
830
831 main()
832 {
833         SVCXPRT *transp;
834         int nuser();
835
836         transp = svcudp_create(RPC_ANYSOCK);
837         if (transp == NULL){
838                 fprintf(stderr, "can't create an RPC server\en");
839                 exit(1);
840         }
841         pmap_unset(RUSERSPROG, RUSERSVERS);
842         if (!svc_register(transp, RUSERSPROG, RUSERSVERS,
843                           nuser, IPPROTO_UDP)) {
844                 fprintf(stderr, "can't register RUSER service\en");
845                 exit(1);
846         }
847         svc_run();  /* \fINever returns\fP */
848         fprintf(stderr, "should never reach this point\en");
849 }
850
851 nuser(rqstp, transp)
852         struct svc_req *rqstp;
853         SVCXPRT *transp;
854 {
855         unsigned long nusers;
856
857         switch (rqstp->rq_proc) {
858         case NULLPROC:
859                 if (!svc_sendreply(transp, xdr_void, 0))
860                         fprintf(stderr, "can't reply to RPC call\en");
861                 return;
862         case RUSERSPROC_NUM:
863 .ft I
864                 /*
865                  * Code here to compute the number of users
866                  * and assign it to the variable \fInusers\fP
867                  */
868 .ft CW
869                 if (!svc_sendreply(transp, xdr_u_long, &nusers)) 
870                         fprintf(stderr, "can't reply to RPC call\en");
871                 return;
872         default:
873                 svcerr_noproc(transp);
874                 return;
875         }
876 }
877 .DE
878 .LP
879 First, the server gets a transport handle, which is used
880 for receiving and replying to RPC messages.
881 .I registerrpc() 
882 uses
883 .I svcudp_create()
884 to get a UDP handle.
885 If you require a more reliable protocol, call
886 .I svctcp_create()
887 instead.
888 If the argument to
889 .I svcudp_create() 
890 is
891 .I RPC_ANYSOCK
892 the RPC library creates a socket
893 on which to receive and reply to RPC calls.  Otherwise,
894 .I svcudp_create() 
895 expects its argument to be a valid socket number.
896 If you specify your own socket, it can be bound or unbound.
897 If it is bound to a port by the user, the port numbers of
898 .I svcudp_create() 
899 and
900 .I clnttcp_create()
901 (the low-level client routine) must match.
902 .LP
903 If the user specifies the
904 .I RPC_ANYSOCK 
905 argument, the RPC library routines will open sockets.
906 Otherwise they will expect the user to do so.  The routines
907 .I svcudp_create() 
908 and 
909 .I clntudp_create()
910 will cause the RPC library routines to
911 .I bind() 
912 their socket if it is not bound already.
913 .LP
914 A service may choose to register its port number with the
915 local portmapper service.  This is done is done by specifying
916 a non-zero protocol number in
917 .I svc_register ().
918 Incidently, a client can discover the server's port number by 
919 consulting the portmapper on their server's machine.  This can 
920 be done automatically by specifying a zero port number in 
921 .I clntudp_create() 
922 or
923 .I clnttcp_create ().
924 .LP
925 After creating an
926 .I SVCXPRT ,
927 the next step is to call
928 .I pmap_unset()
929 so that if the
930 .I nusers() 
931 server crashed earlier,
932 any previous trace of it is erased before restarting.
933 More precisely,
934 .I pmap_unset() 
935 erases the entry for
936 .I RUSERSPROG
937 from the port mapper's tables.
938 .LP
939 Finally, we associate the program number for
940 .I nusers() 
941 with the procedure
942 .I nuser ().
943 The final argument to
944 .I svc_register() 
945 is normally the protocol being used,
946 which, in this case, is
947 .I IPPROTO_UDP
948 Notice that unlike
949 .I registerrpc (),
950 there are no XDR routines involved
951 in the registration process.
952 Also, registration is done on the program,
953 rather than procedure, level.
954 .LP
955 The user routine
956 .I nuser() 
957 must call and dispatch the appropriate XDR routines
958 based on the procedure number.
959 Note that
960 two things are handled by
961 .I nuser() 
962 that
963 .I registerrpc() 
964 handles automatically.
965 The first is that procedure
966 .I NULLPROC
967 (currently zero) returns with no results.
968 This can be used as a simple test
969 for detecting if a remote program is running.
970 Second, there is a check for invalid procedure numbers.
971 If one is detected,
972 .I svcerr_noproc()
973 is called to handle the error.
974 .KS
975 .LP
976 The user service routine serializes the results and returns
977 them to the RPC caller via
978 .I svc_sendreply()
979 Its first parameter is the
980 .I SVCXPRT
981 handle, the second is the XDR routine,
982 and the third is a pointer to the data to be returned.
983 Not illustrated above is how a server
984 handles an RPC program that receives data.
985 As an example, we can add a procedure
986 .I RUSERSPROC_BOOL
987 which has an argument
988 .I nusers (),
989 and returns
990 .I TRUE 
991 or
992 .I FALSE 
993 depending on whether there are nusers logged on.
994 It would look like this:
995 .ie t .DS
996 .el .DS L
997 .ft CW
998 case RUSERSPROC_BOOL: {
999         int bool;
1000         unsigned nuserquery;
1001
1002         if (!svc_getargs(transp, xdr_u_int, &nuserquery) {
1003                 svcerr_decode(transp);
1004                 return;
1005         }
1006 .ft I
1007         /*
1008          * Code to set \fInusers\fP = number of users
1009          */
1010 .ft CW
1011         if (nuserquery == nusers)
1012                 bool = TRUE;
1013         else
1014                 bool = FALSE;
1015         if (!svc_sendreply(transp, xdr_bool, &bool)) {
1016                  fprintf(stderr, "can't reply to RPC call\en");
1017                  return (1);
1018         }
1019         return;
1020 }
1021 .DE
1022 .KE
1023 .LP
1024 The relevant routine is
1025 .I svc_getargs()
1026 which takes an
1027 .I SVCXPRT
1028 handle, the XDR routine,
1029 and a pointer to where the input is to be placed as arguments.
1030 .NH 2
1031 \&Memory Allocation with XDR
1032 .IX "memory allocation with XDR"
1033 .IX XDR "memory allocation"
1034 .LP
1035 XDR routines not only do input and output,
1036 they also do memory allocation.
1037 This is why the second parameter of
1038 .I xdr_array()
1039 is a pointer to an array, rather than the array itself.
1040 If it is
1041 .I NULL ,
1042 then
1043 .I xdr_array()
1044 allocates space for the array and returns a pointer to it,
1045 putting the size of the array in the third argument.
1046 As an example, consider the following XDR routine
1047 .I xdr_chararr1()
1048 which deals with a fixed array of bytes with length
1049 .I SIZE .
1050 .ie t .DS
1051 .el .DS L
1052 .ft CW
1053 xdr_chararr1(xdrsp, chararr)
1054         XDR *xdrsp;
1055         char chararr[];
1056 {
1057         char *p;
1058         int len;
1059
1060         p = chararr;
1061         len = SIZE;
1062         return (xdr_bytes(xdrsp, &p, &len, SIZE));
1063 }
1064 .DE
1065 If space has already been allocated in
1066 .I chararr ,
1067 it can be called from a server like this:
1068 .ie t .DS
1069 .el .DS L
1070 .ft CW
1071 char chararr[SIZE];
1072
1073 svc_getargs(transp, xdr_chararr1, chararr);
1074 .DE
1075 If you want XDR to do the allocation,
1076 you would have to rewrite this routine in the following way:
1077 .ie t .DS
1078 .el .DS L
1079 .ft CW
1080 xdr_chararr2(xdrsp, chararrp)
1081         XDR *xdrsp;
1082         char **chararrp;
1083 {
1084         int len;
1085
1086         len = SIZE;
1087         return (xdr_bytes(xdrsp, charrarrp, &len, SIZE));
1088 }
1089 .DE
1090 Then the RPC call might look like this:
1091 .ie t .DS
1092 .el .DS L
1093 .ft CW
1094 char *arrptr;
1095
1096 arrptr = NULL;
1097 svc_getargs(transp, xdr_chararr2, &arrptr);
1098 .ft I
1099 /*
1100  * Use the result here
1101  */
1102 .ft CW
1103 svc_freeargs(transp, xdr_chararr2, &arrptr);
1104 .DE
1105 Note that, after being used, the character array can be freed with
1106 .I svc_freeargs()
1107 .I svc_freeargs() 
1108 will not attempt to free any memory if the variable indicating it 
1109 is NULL.  For example, in the the routine 
1110 .I xdr_finalexample (),
1111 given earlier, if
1112 .I finalp->string 
1113 was NULL, then it would not be freed.  The same is true for 
1114 .I finalp->simplep .
1115 .LP
1116 To summarize, each XDR routine is responsible
1117 for serializing, deserializing, and freeing memory.
1118 When an XDR routine is called from
1119 .I callrpc()
1120 the serializing part is used.
1121 When called from
1122 .I svc_getargs()
1123 the deserializer is used.
1124 And when called from
1125 .I svc_freeargs()
1126 the memory deallocator is used.  When building simple examples like those
1127 in this section, a user doesn't have to worry 
1128 about the three modes.  
1129 See the
1130 .I "External Data Representation: Sun Technical Notes"
1131 for examples of more sophisticated XDR routines that determine 
1132 which of the three modes they are in and adjust their behavior accordingly.
1133 .KS
1134 .NH 2
1135 \&The Calling Side
1136 .IX RPC "calling side"
1137 .LP
1138 When you use
1139 .I callrpc()
1140 you have no control over the RPC delivery
1141 mechanism or the socket used to transport the data.
1142 To illustrate the layer of RPC that lets you adjust these
1143 parameters, consider the following code to call the
1144 .I nusers
1145 service:
1146 .ie t .DS
1147 .el .DS L
1148 .ft CW
1149 .vs 11
1150 #include <stdio.h>
1151 #include <rpc/rpc.h>
1152 #include <utmp.h>
1153 #include <rpcsvc/rusers.h>
1154 #include <sys/socket.h>
1155 #include <sys/time.h>
1156 #include <netdb.h>
1157
1158 main(argc, argv)
1159         int argc;
1160         char **argv;
1161 {
1162         struct hostent *hp;
1163         struct timeval pertry_timeout, total_timeout;
1164         struct sockaddr_in server_addr;
1165         int sock = RPC_ANYSOCK;
1166         register CLIENT *client;
1167         enum clnt_stat clnt_stat;
1168         unsigned long nusers;
1169
1170         if (argc != 2) {
1171                 fprintf(stderr, "usage: nusers hostname\en");
1172                 exit(-1);
1173         }
1174         if ((hp = gethostbyname(argv[1])) == NULL) {
1175                 fprintf(stderr, "can't get addr for %s\en",argv[1]);
1176                 exit(-1);
1177         }
1178         pertry_timeout.tv_sec = 3;
1179         pertry_timeout.tv_usec = 0;
1180         bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
1181                 hp->h_length);
1182         server_addr.sin_family = AF_INET;
1183         server_addr.sin_port =  0;
1184         if ((client = clntudp_create(&server_addr, RUSERSPROG,
1185           RUSERSVERS, pertry_timeout, &sock)) == NULL) {
1186                 clnt_pcreateerror("clntudp_create");
1187                 exit(-1);
1188         }
1189         total_timeout.tv_sec = 20;
1190         total_timeout.tv_usec = 0;
1191         clnt_stat = clnt_call(client, RUSERSPROC_NUM, xdr_void,
1192                 0, xdr_u_long, &nusers, total_timeout);
1193         if (clnt_stat != RPC_SUCCESS) {
1194                 clnt_perror(client, "rpc");
1195                 exit(-1);
1196         }
1197         clnt_destroy(client);
1198         close(sock);
1199         exit(0);
1200 }
1201 .vs
1202 .DE
1203 .KE
1204 The low-level version of
1205 .I callrpc()
1206 is
1207 .I clnt_call()
1208 which takes a
1209 .I CLIENT
1210 pointer rather than a host name.  The parameters to
1211 .I clnt_call() 
1212 are a
1213 .I CLIENT 
1214 pointer, the procedure number,
1215 the XDR routine for serializing the argument,
1216 a pointer to the argument,
1217 the XDR routine for deserializing the return value,
1218 a pointer to where the return value will be placed,
1219 and the time in seconds to wait for a reply.
1220 .LP
1221 The
1222 .I CLIENT 
1223 pointer is encoded with the transport mechanism.
1224 .I callrpc()
1225 uses UDP, thus it calls
1226 .I clntudp_create() 
1227 to get a
1228 .I CLIENT 
1229 pointer.  To get TCP (Transmission Control Protocol), you would use
1230 .I clnttcp_create() .
1231 .LP
1232 The parameters to
1233 .I clntudp_create() 
1234 are the server address, the program number, the version number,
1235 a timeout value (between tries), and a pointer to a socket.
1236 The final argument to
1237 .I clnt_call() 
1238 is the total time to wait for a response.
1239 Thus, the number of tries is the
1240 .I clnt_call() 
1241 timeout divided by the
1242 .I clntudp_create() 
1243 timeout.
1244 .LP
1245 Note that the
1246 .I clnt_destroy()
1247 call
1248 always deallocates the space associated with the
1249 .I CLIENT 
1250 handle.  It closes the socket associated with the
1251 .I CLIENT 
1252 handle, however, only if the RPC library opened it.  It the
1253 socket was opened by the user, it stays open.  This makes it
1254 possible, in cases where there are multiple client handles
1255 using the same socket, to destroy one handle without closing
1256 the socket that other handles are using.
1257 .LP
1258 To make a stream connection, the call to
1259 .I clntudp_create() 
1260 is replaced with a call to
1261 .I clnttcp_create() .
1262 .DS
1263 .ft CW
1264 clnttcp_create(&server_addr, prognum, versnum, &sock,
1265                inputsize, outputsize);
1266 .DE
1267 There is no timeout argument; instead, the receive and send buffer
1268 sizes must be specified.  When the
1269 .I clnttcp_create() 
1270 call is made, a TCP connection is established.
1271 All RPC calls using that
1272 .I CLIENT 
1273 handle would use this connection.
1274 The server side of an RPC call using TCP has
1275 .I svcudp_create()
1276 replaced by
1277 .I svctcp_create() .
1278 .DS
1279 .ft CW
1280 transp = svctcp_create(RPC_ANYSOCK, 0, 0);
1281 .DE
1282 The last two arguments to 
1283 .I svctcp_create() 
1284 are send and receive sizes respectively.  If `0' is specified for 
1285 either of these, the system chooses a reasonable default.
1286 .KS
1287 .NH 1
1288 \&Other RPC Features
1289 .IX "RPC" "miscellaneous features"
1290 .IX "miscellaneous RPC features"
1291 .LP
1292 This section discusses some other aspects of RPC
1293 that are occasionally useful.
1294 .NH 2
1295 \&Select on the Server Side
1296 .IX RPC select() RPC \fIselect()\fP
1297 .IX select() "" \fIselect()\fP "on the server side"
1298 .LP
1299 Suppose a process is processing RPC requests
1300 while performing some other activity.
1301 If the other activity involves periodically updating a data structure,
1302 the process can set an alarm signal before calling
1303 .I svc_run()
1304 But if the other activity
1305 involves waiting on a a file descriptor, the
1306 .I svc_run()
1307 call won't work.
1308 The code for
1309 .I svc_run()
1310 is as follows:
1311 .ie t .DS
1312 .el .DS L
1313 .ft CW
1314 .vs 11
1315 void
1316 svc_run()
1317 {
1318         fd_set readfds;
1319         int dtbsz = getdtablesize();
1320
1321         for (;;) {
1322                 readfds = svc_fds;
1323                 switch (select(dtbsz, &readfds, NULL,NULL,NULL)) {
1324
1325                 case -1:
1326                         if (errno == EINTR)
1327                                 continue;
1328                         perror("select");
1329                         return;
1330                 case 0:
1331                         break;
1332                 default:
1333                         svc_getreqset(&readfds);
1334                 }
1335         }
1336 }
1337 .vs
1338 .DE
1339 .KE
1340 .LP
1341 You can bypass
1342 .I svc_run()
1343 and call
1344 .I svc_getreqset()
1345 yourself.
1346 All you need to know are the file descriptors
1347 of the socket(s) associated with the programs you are waiting on.
1348 Thus you can have your own
1349 .I select() 
1350 .IX select() "" \fIselect()\fP
1351 that waits on both the RPC socket,
1352 and your own descriptors.  Note that
1353 .I svc_fds() 
1354 is a bit mask of all the file descriptors that RPC is using for 
1355 services.  It can change everytime that
1356 .I any
1357 RPC library routine is called, because descriptors are constantly 
1358 being opened and closed, for example for TCP connections.
1359 .NH 2
1360 \&Broadcast RPC
1361 .IX "broadcast RPC"
1362 .IX RPC "broadcast"
1363 .LP
1364 The
1365 .I portmapper
1366 is a daemon that converts RPC program numbers
1367 into DARPA protocol port numbers; see the
1368 .I portmap 
1369 man page.  You can't do broadcast RPC without the portmapper.
1370 Here are the main differences between
1371 broadcast RPC and normal RPC calls:
1372 .IP  1.
1373 Normal RPC expects one answer, whereas
1374 broadcast RPC expects many answers
1375 (one or more answer from each responding machine).
1376 .IP  2.
1377 Broadcast RPC can only be supported by packet-oriented (connectionless)
1378 transport protocols like UPD/IP.
1379 .IP  3.
1380 The implementation of broadcast RPC
1381 treats all unsuccessful responses as garbage by filtering them out.
1382 Thus, if there is a version mismatch between the
1383 broadcaster and a remote service,
1384 the user of broadcast RPC never knows.
1385 .IP  4.
1386 All broadcast messages are sent to the portmap port.
1387 Thus, only services that register themselves with their portmapper
1388 are accessible via the broadcast RPC mechanism.
1389 .IP  5.
1390 Broadcast requests are limited in size to the MTU (Maximum Transfer
1391 Unit) of the local network.  For Ethernet, the MTU is 1500 bytes.
1392 .KS
1393 .NH 3
1394 \&Broadcast RPC Synopsis
1395 .IX "broadcast RPC" synopsis
1396 .IX "RPC" "broadcast synopsis"
1397 .ie t .DS
1398 .el .DS L
1399 .ft CW
1400 #include <rpc/pmap_clnt.h>
1401         . . .
1402 enum clnt_stat  clnt_stat;
1403         . . .
1404 clnt_stat = clnt_broadcast(prognum, versnum, procnum,
1405   inproc, in, outproc, out, eachresult)
1406         u_long    prognum;        /* \fIprogram number\fP */
1407         u_long    versnum;        /* \fIversion number\fP */
1408         u_long    procnum;        /* \fIprocedure number\fP */
1409         xdrproc_t inproc;         /* \fIxdr routine for args\fP */
1410         caddr_t   in;             /* \fIpointer to args\fP */
1411         xdrproc_t outproc;        /* \fIxdr routine for results\fP */
1412         caddr_t   out;            /* \fIpointer to results\fP */
1413         bool_t    (*eachresult)();/* \fIcall with each result gotten\fP */
1414 .DE
1415 .KE
1416 The procedure
1417 .I eachresult()
1418 is called each time a valid result is obtained.
1419 It returns a boolean that indicates
1420 whether or not the user wants more responses.
1421 .ie t .DS
1422 .el .DS L
1423 .ft CW
1424 bool_t done;
1425         . . . 
1426 done = eachresult(resultsp, raddr)
1427         caddr_t resultsp;
1428         struct sockaddr_in *raddr; /* \fIAddr of responding machine\fP */
1429 .DE
1430 If
1431 .I done
1432 is
1433 .I TRUE ,
1434 then broadcasting stops and
1435 .I clnt_broadcast()
1436 returns successfully.
1437 Otherwise, the routine waits for another response.
1438 The request is rebroadcast
1439 after a few seconds of waiting.
1440 If no responses come back,
1441 the routine returns with
1442 .I RPC_TIMEDOUT .
1443 .NH 2
1444 \&Batching
1445 .IX "batching"
1446 .IX RPC "batching"
1447 .LP
1448 The RPC architecture is designed so that clients send a call message,
1449 and wait for servers to reply that the call succeeded.
1450 This implies that clients do not compute
1451 while servers are processing a call.
1452 This is inefficient if the client does not want or need
1453 an acknowledgement for every message sent.
1454 It is possible for clients to continue computing
1455 while waiting for a response,
1456 using RPC batch facilities.
1457 .LP
1458 RPC messages can be placed in a \*Qpipeline\*U of calls
1459 to a desired server; this is called batching.
1460 Batching assumes that:
1461 1) each RPC call in the pipeline requires no response from the server,
1462 and the server does not send a response message; and
1463 2) the pipeline of calls is transported on a reliable
1464 byte stream transport such as TCP/IP.
1465 Since the server does not respond to every call,
1466 the client can generate new calls in parallel
1467 with the server executing previous calls.
1468 Furthermore, the TCP/IP implementation can buffer up
1469 many call messages, and send them to the server in one
1470 .I write()
1471 system call.  This overlapped execution
1472 greatly decreases the interprocess communication overhead of
1473 the client and server processes,
1474 and the total elapsed time of a series of calls.
1475 .LP
1476 Since the batched calls are buffered,
1477 the client should eventually do a nonbatched call
1478 in order to flush the pipeline.
1479 .LP
1480 A contrived example of batching follows.
1481 Assume a string rendering service (like a window system)
1482 has two similar calls: one renders a string and returns void results,
1483 while the other renders a string and remains silent.
1484 The service (using the TCP/IP transport) may look like:
1485 .ie t .DS
1486 .el .DS L
1487 .ft CW
1488 #include <stdio.h>
1489 #include <rpc/rpc.h>
1490 #include <suntool/windows.h>
1491
1492 void windowdispatch();
1493
1494 main()
1495 {
1496         SVCXPRT *transp;
1497
1498         transp = svctcp_create(RPC_ANYSOCK, 0, 0);
1499         if (transp == NULL){
1500                 fprintf(stderr, "can't create an RPC server\en");
1501                 exit(1);
1502         }
1503         pmap_unset(WINDOWPROG, WINDOWVERS);
1504         if (!svc_register(transp, WINDOWPROG, WINDOWVERS,
1505           windowdispatch, IPPROTO_TCP)) {
1506                 fprintf(stderr, "can't register WINDOW service\en");
1507                 exit(1);
1508         }
1509         svc_run();  /* \fINever returns\fP */
1510         fprintf(stderr, "should never reach this point\en");
1511 }
1512
1513 void
1514 windowdispatch(rqstp, transp)
1515         struct svc_req *rqstp;
1516         SVCXPRT *transp;
1517 {
1518         char *s = NULL;
1519
1520         switch (rqstp->rq_proc) {
1521         case NULLPROC:
1522                 if (!svc_sendreply(transp, xdr_void, 0)) 
1523                         fprintf(stderr, "can't reply to RPC call\en");
1524                 return;
1525         case RENDERSTRING:
1526                 if (!svc_getargs(transp, xdr_wrapstring, &s)) {
1527                         fprintf(stderr, "can't decode arguments\en");
1528 .ft I
1529                         /*
1530                          * Tell caller he screwed up
1531                          */
1532 .ft CW
1533                         svcerr_decode(transp);
1534                         break;
1535                 }
1536 .ft I
1537                 /*
1538                  * Code here to render the string \fIs\fP
1539                  */
1540 .ft CW
1541                 if (!svc_sendreply(transp, xdr_void, NULL)) 
1542                         fprintf(stderr, "can't reply to RPC call\en");
1543                 break;
1544         case RENDERSTRING_BATCHED:
1545                 if (!svc_getargs(transp, xdr_wrapstring, &s)) {
1546                         fprintf(stderr, "can't decode arguments\en");
1547 .ft I
1548                         /*
1549                          * We are silent in the face of protocol errors
1550                          */
1551 .ft CW
1552                         break;
1553                 }
1554 .ft I
1555                 /*
1556                  * Code here to render string s, but send no reply!
1557                  */
1558 .ft CW
1559                 break;
1560         default:
1561                 svcerr_noproc(transp);
1562                 return;
1563         }
1564 .ft I
1565         /*
1566          * Now free string allocated while decoding arguments
1567          */
1568 .ft CW
1569         svc_freeargs(transp, xdr_wrapstring, &s);
1570 }
1571 .DE
1572 Of course the service could have one procedure
1573 that takes the string and a boolean
1574 to indicate whether or not the procedure should respond.
1575 .LP
1576 In order for a client to take advantage of batching,
1577 the client must perform RPC calls on a TCP-based transport
1578 and the actual calls must have the following attributes:
1579 1) the result's XDR routine must be zero
1580 .I NULL ),
1581 and 2) the RPC call's timeout must be zero.
1582 .KS
1583 .LP
1584 Here is an example of a client that uses batching to render a
1585 bunch of strings; the batching is flushed when the client gets
1586 a null string (EOF):
1587 .ie t .DS
1588 .el .DS L
1589 .ft CW
1590 .vs 11
1591 #include <stdio.h>
1592 #include <rpc/rpc.h>
1593 #include <sys/socket.h>
1594 #include <sys/time.h>
1595 #include <netdb.h>
1596 #include <suntool/windows.h>
1597
1598 main(argc, argv)
1599         int argc;
1600         char **argv;
1601 {
1602         struct hostent *hp;
1603         struct timeval pertry_timeout, total_timeout;
1604         struct sockaddr_in server_addr;
1605         int sock = RPC_ANYSOCK;
1606         register CLIENT *client;
1607         enum clnt_stat clnt_stat;
1608         char buf[1000], *s = buf;
1609
1610         if ((client = clnttcp_create(&server_addr,
1611           WINDOWPROG, WINDOWVERS, &sock, 0, 0)) == NULL) {
1612                 perror("clnttcp_create");
1613                 exit(-1);
1614         }
1615         total_timeout.tv_sec = 0;
1616         total_timeout.tv_usec = 0;
1617         while (scanf("%s", s) != EOF) {
1618                 clnt_stat = clnt_call(client, RENDERSTRING_BATCHED,
1619                         xdr_wrapstring, &s, NULL, NULL, total_timeout);
1620                 if (clnt_stat != RPC_SUCCESS) {
1621                         clnt_perror(client, "batched rpc");
1622                         exit(-1);
1623                 }
1624         }
1625
1626         /* \fINow flush the pipeline\fP */
1627
1628         total_timeout.tv_sec = 20;
1629         clnt_stat = clnt_call(client, NULLPROC, xdr_void, NULL,
1630                 xdr_void, NULL, total_timeout);
1631         if (clnt_stat != RPC_SUCCESS) {
1632                 clnt_perror(client, "rpc");
1633                 exit(-1);
1634         }
1635         clnt_destroy(client);
1636         exit(0);
1637 }
1638 .vs
1639 .DE
1640 .KE
1641 Since the server sends no message,
1642 the clients cannot be notified of any of the failures that may occur.
1643 Therefore, clients are on their own when it comes to handling errors.
1644 .LP
1645 The above example was completed to render
1646 all of the (2000) lines in the file
1647 .I /etc/termcap .
1648 The rendering service did nothing but throw the lines away.
1649 The example was run in the following four configurations:
1650 1) machine to itself, regular RPC;
1651 2) machine to itself, batched RPC;
1652 3) machine to another, regular RPC; and
1653 4) machine to another, batched RPC.
1654 The results are as follows:
1655 1) 50 seconds;
1656 2) 16 seconds;
1657 3) 52 seconds;
1658 4) 10 seconds.
1659 Running
1660 .I fscanf()
1661 on
1662 .I /etc/termcap
1663 only requires six seconds.
1664 These timings show the advantage of protocols
1665 that allow for overlapped execution,
1666 though these protocols are often hard to design.
1667 .NH 2
1668 \&Authentication
1669 .IX "authentication"
1670 .IX "RPC" "authentication"
1671 .LP
1672 In the examples presented so far,
1673 the caller never identified itself to the server,
1674 and the server never required an ID from the caller.
1675 Clearly, some network services, such as a network filesystem,
1676 require stronger security than what has been presented so far.
1677 .LP
1678 In reality, every RPC call is authenticated by
1679 the RPC package on the server, and similarly,
1680 the RPC client package generates and sends authentication parameters.
1681 Just as different transports (TCP/IP or UDP/IP)
1682 can be used when creating RPC clients and servers,
1683 different forms of authentication can be associated with RPC clients;
1684 the default authentication type used as a default is type
1685 .I none .
1686 .LP
1687 The authentication subsystem of the RPC package is open ended.
1688 That is, numerous types of authentication are easy to support.
1689 .NH 3
1690 \&UNIX Authentication
1691 .IX "UNIX Authentication"
1692 .IP "\fIThe Client Side\fP"
1693 .LP
1694 When a caller creates a new RPC client handle as in:
1695 .DS
1696 .ft CW
1697 clnt = clntudp_create(address, prognum, versnum,
1698                       wait, sockp)
1699 .DE
1700 the appropriate transport instance defaults
1701 the associate authentication handle to be
1702 .DS
1703 .ft CW
1704 clnt->cl_auth = authnone_create();
1705 .DE
1706 The RPC client can choose to use
1707 .I UNIX
1708 style authentication by setting
1709 .I clnt\->cl_auth
1710 after creating the RPC client handle:
1711 .DS
1712 .ft CW
1713 clnt->cl_auth = authunix_create_default();
1714 .DE
1715 This causes each RPC call associated with
1716 .I clnt
1717 to carry with it the following authentication credentials structure:
1718 .ie t .DS
1719 .el .DS L
1720 .ft I
1721 /*
1722  * UNIX style credentials.
1723  */
1724 .ft CW
1725 struct authunix_parms {
1726     u_long  aup_time;       /* \fIcredentials creation time\fP */
1727     char    *aup_machname;  /* \fIhost name where client is\fP */
1728     int     aup_uid;        /* \fIclient's UNIX effective uid\fP */
1729     int     aup_gid;        /* \fIclient's current group id\fP */
1730     u_int   aup_len;        /* \fIelement length of aup_gids\fP */
1731     int     *aup_gids;      /* \fIarray of groups user is in\fP */
1732 };
1733 .DE
1734 These fields are set by
1735 .I authunix_create_default()
1736 by invoking the appropriate system calls.
1737 Since the RPC user created this new style of authentication,
1738 the user is responsible for destroying it with:
1739 .DS
1740 .ft CW
1741 auth_destroy(clnt->cl_auth);
1742 .DE
1743 This should be done in all cases, to conserve memory.
1744 .sp
1745 .IP "\fIThe Server Side\fP"
1746 .LP
1747 Service implementors have a harder time dealing with authentication issues
1748 since the RPC package passes the service dispatch routine a request
1749 that has an arbitrary authentication style associated with it.
1750 Consider the fields of a request handle passed to a service dispatch routine:
1751 .ie t .DS
1752 .el .DS L
1753 .ft I
1754 /*
1755  * An RPC Service request
1756  */
1757 .ft CW
1758 struct svc_req {
1759     u_long    rq_prog;          /* \fIservice program number\fP */
1760     u_long    rq_vers;          /* \fIservice protocol vers num\fP */
1761     u_long    rq_proc;          /* \fIdesired procedure number\fP */
1762     struct opaque_auth rq_cred; /* \fIraw credentials from wire\fP */
1763     caddr_t   rq_clntcred;  /* \fIcredentials (read only)\fP */
1764 };
1765 .DE
1766 The
1767 .I rq_cred
1768 is mostly opaque, except for one field of interest:
1769 the style or flavor of authentication credentials:
1770 .ie t .DS
1771 .el .DS L
1772 .ft I
1773 /*
1774  * Authentication info.  Mostly opaque to the programmer.
1775  */
1776 .ft CW
1777 struct opaque_auth {
1778     enum_t  oa_flavor;  /* \fIstyle of credentials\fP */
1779     caddr_t oa_base;    /* \fIaddress of more auth stuff\fP */
1780     u_int   oa_length;  /* \fInot to exceed \fIMAX_AUTH_BYTES */
1781 };
1782 .DE
1783 .IX RPC guarantees
1784 The RPC package guarantees the following
1785 to the service dispatch routine:
1786 .IP  1.
1787 That the request's
1788 .I rq_cred
1789 is well formed.  Thus the service implementor may inspect the request's
1790 .I rq_cred.oa_flavor
1791 to determine which style of authentication the caller used.
1792 The service implementor may also wish to inspect the other fields of
1793 .I rq_cred
1794 if the style is not one of the styles supported by the RPC package.
1795 .IP  2.
1796 That the request's
1797 .I rq_clntcred
1798 field is either
1799 .I NULL 
1800 or points to a well formed structure
1801 that corresponds to a supported style of authentication credentials.
1802 Remember that only
1803 .I unix
1804 style is currently supported, so (currently)
1805 .I rq_clntcred
1806 could be cast to a pointer to an
1807 .I authunix_parms
1808 structure.  If
1809 .I rq_clntcred
1810 is
1811 .I NULL ,
1812 the service implementor may wish to inspect the other (opaque) fields of
1813 .I rq_cred
1814 in case the service knows about a new type of authentication
1815 that the RPC package does not know about.
1816 .LP
1817 Our remote users service example can be extended so that
1818 it computes results for all users except UID 16:
1819 .ie t .DS
1820 .el .DS L
1821 .ft CW
1822 .vs 11
1823 nuser(rqstp, transp)
1824         struct svc_req *rqstp;
1825         SVCXPRT *transp;
1826 {
1827         struct authunix_parms *unix_cred;
1828         int uid;
1829         unsigned long nusers;
1830
1831 .ft I
1832         /*
1833          * we don't care about authentication for null proc
1834          */
1835 .ft CW
1836         if (rqstp->rq_proc == NULLPROC) {
1837                 if (!svc_sendreply(transp, xdr_void, 0)) {
1838                         fprintf(stderr, "can't reply to RPC call\en");
1839                         return (1);
1840                  }
1841                  return;
1842         }
1843 .ft I
1844         /*
1845          * now get the uid
1846          */
1847 .ft CW
1848         switch (rqstp->rq_cred.oa_flavor) {
1849         case AUTH_UNIX:
1850                 unix_cred = 
1851                         (struct authunix_parms *)rqstp->rq_clntcred;
1852                 uid = unix_cred->aup_uid;
1853                 break;
1854         case AUTH_NULL:
1855         default:
1856                 svcerr_weakauth(transp);
1857                 return;
1858         }
1859         switch (rqstp->rq_proc) {
1860         case RUSERSPROC_NUM:
1861 .ft I
1862                 /*
1863                  * make sure caller is allowed to call this proc
1864                  */
1865 .ft CW
1866                 if (uid == 16) {
1867                         svcerr_systemerr(transp);
1868                         return;
1869                 }
1870 .ft I
1871                 /*
1872                  * Code here to compute the number of users
1873                  * and assign it to the variable \fInusers\fP
1874                  */
1875 .ft CW
1876                 if (!svc_sendreply(transp, xdr_u_long, &nusers)) {
1877                         fprintf(stderr, "can't reply to RPC call\en");
1878                         return (1);
1879                 }
1880                 return;
1881         default:
1882                 svcerr_noproc(transp);
1883                 return;
1884         }
1885 }
1886 .vs
1887 .DE
1888 A few things should be noted here.
1889 First, it is customary not to check
1890 the authentication parameters associated with the
1891 .I NULLPROC
1892 (procedure number zero).
1893 Second, if the authentication parameter's type is not suitable
1894 for your service, you should call
1895 .I svcerr_weakauth() .
1896 And finally, the service protocol itself should return status
1897 for access denied; in the case of our example, the protocol
1898 does not have such a status, so we call the service primitive
1899 .I svcerr_systemerr()
1900 instead.
1901 .LP
1902 The last point underscores the relation between
1903 the RPC authentication package and the services;
1904 RPC deals only with 
1905 .I authentication 
1906 and not with individual services' 
1907 .I "access control" .
1908 The services themselves must implement their own access control policies
1909 and reflect these policies as return statuses in their protocols.
1910 .NH 2
1911 \&DES Authentication
1912 .IX RPC DES
1913 .IX RPC authentication
1914 .LP
1915 UNIX authentication is quite easy to defeat.  Instead of using
1916 .I authunix_create_default (),
1917 one can call
1918 .I authunix_create() 
1919 and then modify the RPC authentication handle it returns by filling in
1920 whatever user ID and hostname they wish the server to think they have.
1921 DES authentication is thus recommended for people who want more security
1922 than UNIX authentication offers.
1923 .LP
1924 The details of the DES authentication protocol are complicated and
1925 are not explained here.  
1926 See
1927 .I "Remote Procedure Calls: Protocol Specification"
1928 for the details.
1929 .LP
1930 In  order for  DES authentication   to  work, the
1931 .I keyserv(8c) 
1932 daemon must be running  on both  the  server  and client machines.  The
1933 users on  these machines  need  public  keys  assigned by  the network
1934 administrator in  the
1935 .I publickey(5) 
1936 database.  And,  they  need to have decrypted  their  secret keys
1937 using  their  login   password.  This automatically happens when one
1938 logs in using
1939 .I login(1) ,
1940 or can be done manually using
1941 .I keylogin(1) .
1942 The
1943 .I "Network Services"
1944 chapter
1945 .\" XXX
1946 explains more how to setup secure networking.
1947 .sp
1948 .IP "\fIClient Side\fP"
1949 .LP
1950 If a client wishes to use DES authentication, it must set its
1951 authentication handle appropriately.  Here is an example:
1952 .DS
1953 cl->cl_auth =
1954         authdes_create(servername, 60, &server_addr, NULL);
1955 .DE
1956 The first argument is the network name or \*Qnetname\*U of the owner of
1957 the server process.  Typically, server processes are root processes
1958 and their netname can be derived using the following call:
1959 .DS
1960 char servername[MAXNETNAMELEN];
1961
1962 host2netname(servername, rhostname, NULL);
1963 .DE
1964 Here,
1965 .I rhostname
1966 is the hostname of the machine the server process is running on.
1967 .I host2netname() 
1968 fills in
1969 .I servername
1970 to contain this root process's netname.  If the
1971 server process was run by a regular user, one could use the call
1972 .I user2netname() 
1973 instead.  Here is an example for a server process with the same user
1974 ID as the client:
1975 .DS
1976 char servername[MAXNETNAMELEN];
1977
1978 user2netname(servername, getuid(), NULL);
1979 .DE
1980 The last argument to both of these calls,
1981 .I user2netname() 
1982 and
1983 .I host2netname (),
1984 is the name of the naming domain where the server is located.  The
1985 .I NULL 
1986 used here means \*Quse the local domain name.\*U
1987 .LP
1988 The second argument to
1989 .I authdes_create() 
1990 is a lifetime for the credential.  Here it is set to sixty
1991 seconds.  What that means is that the credential will expire 60
1992 seconds from now.  If some mischievous user tries to reuse the
1993 credential, the server RPC subsystem will recognize that it has
1994 expired and not grant any requests.  If the same mischievous user
1995 tries to reuse the credential within the sixty second lifetime,
1996 he will still be rejected because the server RPC subsystem
1997 remembers which credentials it has already seen in the near past,
1998 and will not grant requests to duplicates.
1999 .LP
2000 The third argument to
2001 .I authdes_create() 
2002 is the address of the host to synchronize with.  In order for DES
2003 authentication to work, the server and client must agree upon the
2004 time.  Here we pass the address of the server itself, so the
2005 client and server will both be using the same time: the server's
2006 time.  The argument can be
2007 .I NULL ,
2008 which means \*Qdon't bother synchronizing.\*U You should only do this
2009 if you are sure the client and server are already synchronized.
2010 .LP
2011 The final argument to
2012 .I authdes_create() 
2013 is the address of a DES encryption key to use for encrypting
2014 timestamps and data.  If this argument is
2015 .I NULL ,
2016 as it is in this example, a random key will be chosen.  The client
2017 may find out the encryption key being used by consulting the
2018 .I ah_key 
2019 field of the authentication handle.
2020 .sp
2021 .IP "\fIServer Side\fP"
2022 .LP
2023 The server side is a lot simpler than the client side.  Here is the
2024 previous example rewritten to use
2025 .I AUTH_DES
2026 instead of
2027 .I AUTH_UNIX :
2028 .ie t .DS
2029 .el .DS L
2030 .ft CW
2031 .vs 11
2032 #include <sys/time.h>
2033 #include <rpc/auth_des.h>
2034         . . .
2035         . . .
2036 nuser(rqstp, transp)
2037         struct svc_req *rqstp;
2038         SVCXPRT *transp;
2039 {
2040         struct authdes_cred *des_cred;
2041         int uid;
2042         int gid;
2043         int gidlen;
2044         int gidlist[10];
2045 .ft I
2046         /*
2047          * we don't care about authentication for null proc
2048          */
2049 .ft CW
2050
2051         if (rqstp->rq_proc == NULLPROC) { 
2052                 /* \fIsame as before\fP */
2053         }
2054
2055 .ft I
2056         /*
2057          * now get the uid
2058          */
2059 .ft CW
2060         switch (rqstp->rq_cred.oa_flavor) {
2061         case AUTH_DES:
2062                 des_cred =
2063                         (struct authdes_cred *) rqstp->rq_clntcred;
2064                 if (! netname2user(des_cred->adc_fullname.name,
2065                         &uid, &gid, &gidlen, gidlist))
2066                 {
2067                         fprintf(stderr, "unknown user: %s\en",
2068                                 des_cred->adc_fullname.name);
2069                         svcerr_systemerr(transp);
2070                         return;
2071                 }
2072                 break;
2073         case AUTH_NULL:
2074         default:
2075                 svcerr_weakauth(transp);
2076                 return;
2077         }
2078
2079 .ft I
2080         /*
2081          * The rest is the same as before
2082          */     
2083 .ft CW
2084 .vs
2085 .DE
2086 Note the use of the routine
2087 .I netname2user (),
2088 the inverse of
2089 .I user2netname ():
2090 it takes a network ID and converts to a unix ID.
2091 .I netname2user () 
2092 also supplies the group IDs which we don't use in this example,
2093 but which may be useful to other UNIX programs.
2094 .NH 2
2095 \&Using Inetd
2096 .IX inetd "" "using \fIinetd\fP"
2097 .LP
2098 An RPC server can be started from
2099 .I inetd
2100 The only difference from the usual code is that the service
2101 creation routine should be called in the following form:
2102 .ie t .DS
2103 .el .DS L
2104 .ft CW
2105 transp = svcudp_create(0);     /* \fIFor UDP\fP */
2106 transp = svctcp_create(0,0,0); /* \fIFor listener TCP sockets\fP */
2107 transp = svcfd_create(0,0,0);  /* \fIFor connected TCP sockets\fP */
2108 .DE
2109 since
2110 .I inet
2111 passes a socket as file descriptor 0.
2112 Also,
2113 .I svc_register()
2114 should be called as
2115 .ie t .DS
2116 .el .DS L
2117 .ft CW
2118 svc_register(transp, PROGNUM, VERSNUM, service, 0);
2119 .DE
2120 with the final flag as 0,
2121 since the program would already be registered by
2122 .I inetd
2123 Remember that if you want to exit
2124 from the server process and return control to
2125 .I inet
2126 you need to explicitly exit, since
2127 .I svc_run()
2128 never returns.
2129 .LP
2130 The format of entries in 
2131 .I /etc/inetd.conf 
2132 for RPC services is in one of the following two forms:
2133 .ie t .DS
2134 .el .DS L
2135 .ft CW
2136 p_name/version dgram  rpc/udp wait/nowait user server args
2137 p_name/version stream rpc/tcp wait/nowait user server args
2138 .DE
2139 where
2140 .I p_name
2141 is the symbolic name of the program as it appears in
2142 .I rpc(5) ,
2143 .I server
2144 is the program implementing the server,
2145 and
2146 .I program
2147 and
2148 .I version
2149 are the program and version numbers of the service.
2150 For more information, see
2151 .I inetd.conf(5) .
2152 .LP
2153 If the same program handles multiple versions,
2154 then the version number can be a range,
2155 as in this example:
2156 .ie t .DS
2157 .el .DS L
2158 .ft CW
2159 rstatd/1-2 dgram rpc/udp wait root /usr/etc/rpc.rstatd
2160 .DE
2161 .NH 1
2162 \&More Examples
2163 .sp 1
2164 .NH 2
2165 \&Versions
2166 .IX "versions"
2167 .IX "RPC" "versions"
2168 .LP
2169 By convention, the first version number of program
2170 .I PROG
2171 is
2172 .I PROGVERS_ORIG
2173 and the most recent version is
2174 .I PROGVERS
2175 Suppose there is a new version of the
2176 .I user
2177 program that returns an
2178 .I "unsigned short"
2179 rather than a
2180 .I long .
2181 If we name this version
2182 .I RUSERSVERS_SHORT
2183 then a server that wants to support both versions
2184 would do a double register.
2185 .ie t .DS
2186 .el .DS L
2187 .ft CW
2188 if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG,
2189   nuser, IPPROTO_TCP)) {
2190         fprintf(stderr, "can't register RUSER service\en");
2191         exit(1);
2192 }
2193 if (!svc_register(transp, RUSERSPROG, RUSERSVERS_SHORT,
2194   nuser, IPPROTO_TCP)) {
2195         fprintf(stderr, "can't register RUSER service\en");
2196         exit(1);
2197 }
2198 .DE
2199 Both versions can be handled by the same C procedure:
2200 .ie t .DS
2201 .el .DS L
2202 .ft CW
2203 .vs 11
2204 nuser(rqstp, transp)
2205         struct svc_req *rqstp;
2206         SVCXPRT *transp;
2207 {
2208         unsigned long nusers;
2209         unsigned short nusers2;
2210
2211         switch (rqstp->rq_proc) {
2212         case NULLPROC:
2213                 if (!svc_sendreply(transp, xdr_void, 0)) {
2214                         fprintf(stderr, "can't reply to RPC call\en");
2215             return (1);
2216                 }
2217                 return;
2218         case RUSERSPROC_NUM:
2219 .ft I
2220                 /*
2221          * Code here to compute the number of users
2222          * and assign it to the variable \fInusers\fP
2223                  */
2224 .ft CW
2225                 nusers2 = nusers;
2226                 switch (rqstp->rq_vers) {
2227                 case RUSERSVERS_ORIG:
2228             if (!svc_sendreply(transp, xdr_u_long, 
2229                     &nusers)) {
2230                 fprintf(stderr,"can't reply to RPC call\en");
2231                         }
2232                         break;
2233                 case RUSERSVERS_SHORT:
2234             if (!svc_sendreply(transp, xdr_u_short, 
2235                     &nusers2)) {
2236                 fprintf(stderr,"can't reply to RPC call\en");
2237                         }
2238                         break;
2239                 }
2240         default:
2241                 svcerr_noproc(transp);
2242                 return;
2243         }
2244 }
2245 .vs
2246 .DE
2247 .KS
2248 .NH 2
2249 \&TCP
2250 .IX "TCP"
2251 .LP
2252 Here is an example that is essentially
2253 .I rcp.
2254 The initiator of the RPC
2255 .I snd
2256 call takes its standard input and sends it to the server
2257 .I rcv
2258 which prints it on standard output.
2259 The RPC call uses TCP.
2260 This also illustrates an XDR procedure that behaves differently
2261 on serialization than on deserialization.
2262 .ie t .DS
2263 .el .DS L
2264 .vs 11
2265 .ft I
2266 /*
2267  * The xdr routine:
2268  *              on decode, read from wire, write onto fp
2269  *              on encode, read from fp, write onto wire
2270  */
2271 .ft CW
2272 #include <stdio.h>
2273 #include <rpc/rpc.h>
2274
2275 xdr_rcp(xdrs, fp)
2276         XDR *xdrs;
2277         FILE *fp;
2278 {
2279         unsigned long size;
2280         char buf[BUFSIZ], *p;
2281
2282         if (xdrs->x_op == XDR_FREE)/* nothing to free */
2283                 return 1;
2284         while (1) {
2285                 if (xdrs->x_op == XDR_ENCODE) {
2286                         if ((size = fread(buf, sizeof(char), BUFSIZ,
2287                           fp)) == 0 && ferror(fp)) {
2288                                 fprintf(stderr, "can't fread\en");
2289                                 return (1);
2290                         }
2291                 }
2292                 p = buf;
2293                 if (!xdr_bytes(xdrs, &p, &size, BUFSIZ))
2294                         return 0;
2295                 if (size == 0)
2296                         return 1;
2297                 if (xdrs->x_op == XDR_DECODE) {
2298                         if (fwrite(buf, sizeof(char), size,
2299                           fp) != size) {
2300                                 fprintf(stderr, "can't fwrite\en");
2301                                 return (1);
2302                         }
2303                 }
2304         }
2305 }
2306 .vs
2307 .DE
2308 .KE
2309 .ie t .DS
2310 .el .DS L
2311 .vs 11
2312 .ft I
2313 /*
2314  * The sender routines
2315  */
2316 .ft CW
2317 #include <stdio.h>
2318 #include <netdb.h>
2319 #include <rpc/rpc.h>
2320 #include <sys/socket.h>
2321 #include <sys/time.h>
2322
2323 main(argc, argv)
2324         int argc;
2325         char **argv;
2326 {
2327         int xdr_rcp();
2328         int err;
2329
2330         if (argc < 2) {
2331                 fprintf(stderr, "usage: %s servername\en", argv[0]);
2332                 exit(-1);
2333         }
2334         if ((err = callrpctcp(argv[1], RCPPROG, RCPPROC,
2335           RCPVERS, xdr_rcp, stdin, xdr_void, 0) != 0)) {
2336                 clnt_perrno(err);
2337                 fprintf(stderr, "can't make RPC call\en");
2338                 exit(1);
2339         }
2340         exit(0);
2341 }
2342
2343 callrpctcp(host, prognum, procnum, versnum,
2344            inproc, in, outproc, out)
2345         char *host, *in, *out;
2346         xdrproc_t inproc, outproc;
2347 {
2348         struct sockaddr_in server_addr;
2349         int socket = RPC_ANYSOCK;
2350         enum clnt_stat clnt_stat;
2351         struct hostent *hp;
2352         register CLIENT *client;
2353         struct timeval total_timeout;
2354
2355         if ((hp = gethostbyname(host)) == NULL) {
2356                 fprintf(stderr, "can't get addr for '%s'\en", host);
2357                 return (-1);
2358         }
2359         bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
2360                 hp->h_length);
2361         server_addr.sin_family = AF_INET;
2362         server_addr.sin_port =  0;
2363         if ((client = clnttcp_create(&server_addr, prognum,
2364           versnum, &socket, BUFSIZ, BUFSIZ)) == NULL) {
2365                 perror("rpctcp_create");
2366                 return (-1);
2367         }
2368         total_timeout.tv_sec = 20;
2369         total_timeout.tv_usec = 0;
2370         clnt_stat = clnt_call(client, procnum,
2371                 inproc, in, outproc, out, total_timeout);
2372         clnt_destroy(client);
2373         return (int)clnt_stat;
2374 }
2375 .vs
2376 .DE
2377 .ie t .DS
2378 .el .DS L
2379 .vs 11
2380 .ft I
2381 /*
2382  * The receiving routines
2383  */
2384 .ft CW
2385 #include <stdio.h>
2386 #include <rpc/rpc.h>
2387
2388 main()
2389 {
2390         register SVCXPRT *transp;
2391      int rcp_service(), xdr_rcp(); 
2392
2393         if ((transp = svctcp_create(RPC_ANYSOCK,
2394           BUFSIZ, BUFSIZ)) == NULL) {
2395                 fprintf("svctcp_create: error\en");
2396                 exit(1);
2397         }
2398         pmap_unset(RCPPROG, RCPVERS);
2399         if (!svc_register(transp,
2400           RCPPROG, RCPVERS, rcp_service, IPPROTO_TCP)) {
2401                 fprintf(stderr, "svc_register: error\en");
2402                 exit(1);
2403         }
2404         svc_run();  /* \fInever returns\fP */
2405         fprintf(stderr, "svc_run should never return\en");
2406 }
2407
2408 rcp_service(rqstp, transp)
2409         register struct svc_req *rqstp;
2410         register SVCXPRT *transp;
2411 {
2412         switch (rqstp->rq_proc) {
2413         case NULLPROC:
2414                 if (svc_sendreply(transp, xdr_void, 0) == 0) {
2415                         fprintf(stderr, "err: rcp_service");
2416                         return (1);
2417                 }
2418                 return;
2419         case RCPPROC_FP:
2420                 if (!svc_getargs(transp, xdr_rcp, stdout)) {
2421                         svcerr_decode(transp);
2422                         return;
2423                 }
2424                 if (!svc_sendreply(transp, xdr_void, 0)) {
2425                         fprintf(stderr, "can't reply\en");
2426                         return;
2427                 }
2428                 return (0);
2429         default:
2430                 svcerr_noproc(transp);
2431                 return;
2432         }
2433 }
2434 .vs
2435 .DE
2436 .NH 2
2437 \&Callback Procedures
2438 .IX RPC "callback procedures"
2439 .LP
2440 Occasionally, it is useful to have a server become a client,
2441 and make an RPC call back to the process which is its client.
2442 An example is remote debugging,
2443 where the client is a window system program,
2444 and the server is a debugger running on the remote machine.
2445 Most of the time,
2446 the user clicks a mouse button at the debugging window,
2447 which converts this to a debugger command,
2448 and then makes an RPC call to the server
2449 (where the debugger is actually running),
2450 telling it to execute that command.
2451 However, when the debugger hits a breakpoint, the roles are reversed,
2452 and the debugger wants to make an rpc call to the window program,
2453 so that it can inform the user that a breakpoint has been reached.
2454 .LP
2455 In order to do an RPC callback,
2456 you need a program number to make the RPC call on.
2457 Since this will be a dynamically generated program number,
2458 it should be in the transient range,
2459 .I "0x40000000 - 0x5fffffff" .
2460 The routine
2461 .I gettransient()
2462 returns a valid program number in the transient range,
2463 and registers it with the portmapper.
2464 It only talks to the portmapper running on the same machine as the
2465 .I gettransient()
2466 routine itself.  The call to
2467 .I pmap_set()
2468 is a test and set operation,
2469 in that it indivisibly tests whether a program number
2470 has already been registered,
2471 and if it has not, then reserves it.  On return, the
2472 .I sockp
2473 argument will contain a socket that can be used
2474 as the argument to an
2475 .I svcudp_create()
2476 or
2477 .I svctcp_create()
2478 call.
2479 .ie t .DS
2480 .el .DS L
2481 .ft CW
2482 .vs 11
2483 #include <stdio.h>
2484 #include <rpc/rpc.h>
2485 #include <sys/socket.h>
2486
2487 gettransient(proto, vers, sockp)
2488         int proto, vers, *sockp;
2489 {
2490         static int prognum = 0x40000000;
2491         int s, len, socktype;
2492         struct sockaddr_in addr;
2493
2494         switch(proto) {
2495                 case IPPROTO_UDP:
2496                         socktype = SOCK_DGRAM;
2497                         break;
2498                 case IPPROTO_TCP:
2499                         socktype = SOCK_STREAM;
2500                         break;
2501                 default:
2502                         fprintf(stderr, "unknown protocol type\en");
2503                         return 0;
2504         }
2505         if (*sockp == RPC_ANYSOCK) {
2506                 if ((s = socket(AF_INET, socktype, 0)) < 0) {
2507                         perror("socket");
2508                         return (0);
2509                 }
2510                 *sockp = s;
2511         }
2512         else
2513                 s = *sockp;
2514         addr.sin_addr.s_addr = 0;
2515         addr.sin_family = AF_INET;
2516         addr.sin_port = 0;
2517         len = sizeof(addr);
2518 .ft I
2519         /*
2520          * may be already bound, so don't check for error
2521          */
2522 .ft CW
2523         bind(s, &addr, len);
2524         if (getsockname(s, &addr, &len)< 0) {
2525                 perror("getsockname");
2526                 return (0);
2527         }
2528         while (!pmap_set(prognum++, vers, proto, 
2529                 ntohs(addr.sin_port))) continue;
2530         return (prognum-1);
2531 }
2532 .vs
2533 .DE
2534 .SH
2535 Note:
2536 .I
2537 The call to
2538 .I ntohs() 
2539 is necessary to ensure that the port number in
2540 .I "addr.sin_port" ,
2541 which is in 
2542 .I network 
2543 byte order, is passed in 
2544 .I host
2545 byte order (as
2546 .I pmap_set() 
2547 expects).  See the
2548 .I byteorder(3N) 
2549 man page for more details on the conversion of network
2550 addresses from network to host byte order.
2551 .KS
2552 .LP
2553 The following pair of programs illustrate how to use the
2554 .I gettransient()
2555 routine.
2556 The client makes an RPC call to the server,
2557 passing it a transient program number.
2558 Then the client waits around to receive a callback
2559 from the server at that program number.
2560 The server registers the program
2561 .I EXAMPLEPROG
2562 so that it can receive the RPC call
2563 informing it of the callback program number.
2564 Then at some random time (on receiving an
2565 .I ALRM
2566 signal in this example), it sends a callback RPC call,
2567 using the program number it received earlier.
2568 .ie t .DS
2569 .el .DS L
2570 .vs 11
2571 .ft I
2572 /*
2573  * client
2574  */
2575 .ft CW
2576 #include <stdio.h>
2577 #include <rpc/rpc.h>
2578
2579 int callback();
2580 char hostname[256];
2581
2582 main()
2583 {
2584         int x, ans, s;
2585         SVCXPRT *xprt;
2586
2587         gethostname(hostname, sizeof(hostname));
2588         s = RPC_ANYSOCK;
2589         x = gettransient(IPPROTO_UDP, 1, &s);
2590         fprintf(stderr, "client gets prognum %d\en", x);
2591         if ((xprt = svcudp_create(s)) == NULL) {
2592           fprintf(stderr, "rpc_server: svcudp_create\en");
2593                 exit(1);
2594         }
2595 .ft I
2596         /* protocol is 0 - gettransient does registering
2597          */
2598 .ft CW
2599         (void)svc_register(xprt, x, 1, callback, 0);
2600         ans = callrpc(hostname, EXAMPLEPROG, EXAMPLEVERS,
2601                 EXAMPLEPROC_CALLBACK, xdr_int, &x, xdr_void, 0);
2602         if ((enum clnt_stat) ans != RPC_SUCCESS) {
2603                 fprintf(stderr, "call: ");
2604                 clnt_perrno(ans);
2605                 fprintf(stderr, "\en");
2606         }
2607         svc_run();
2608         fprintf(stderr, "Error: svc_run shouldn't return\en");
2609 }
2610
2611 callback(rqstp, transp)
2612         register struct svc_req *rqstp;
2613         register SVCXPRT *transp;
2614 {
2615         switch (rqstp->rq_proc) {
2616                 case 0:
2617                         if (!svc_sendreply(transp, xdr_void, 0)) {
2618                                 fprintf(stderr, "err: exampleprog\en");
2619                                 return (1);
2620                         }
2621                         return (0);
2622                 case 1:
2623                         if (!svc_getargs(transp, xdr_void, 0)) {
2624                                 svcerr_decode(transp);
2625                                 return (1);
2626                         }
2627                         fprintf(stderr, "client got callback\en");
2628                         if (!svc_sendreply(transp, xdr_void, 0)) {
2629                                 fprintf(stderr, "err: exampleprog");
2630                                 return (1);
2631                         }
2632         }
2633 }
2634 .vs
2635 .DE
2636 .KE
2637 .ie t .DS
2638 .el .DS L
2639 .vs 11
2640 .ft I
2641 /*
2642  * server
2643  */
2644 .ft CW
2645 #include <stdio.h>
2646 #include <rpc/rpc.h>
2647 #include <sys/signal.h>
2648
2649 char *getnewprog();
2650 char hostname[256];
2651 int docallback();
2652 int pnum;               /* \fIprogram number for callback routine\fP */
2653
2654 main()
2655 {
2656         gethostname(hostname, sizeof(hostname));
2657         registerrpc(EXAMPLEPROG, EXAMPLEVERS,
2658           EXAMPLEPROC_CALLBACK, getnewprog, xdr_int, xdr_void);
2659         fprintf(stderr, "server going into svc_run\en");
2660         signal(SIGALRM, docallback);
2661         alarm(10);
2662         svc_run();
2663         fprintf(stderr, "Error: svc_run shouldn't return\en");
2664 }
2665
2666 char *
2667 getnewprog(pnump)
2668         char *pnump;
2669 {
2670         pnum = *(int *)pnump;
2671         return NULL;
2672 }
2673
2674 docallback()
2675 {
2676         int ans;
2677
2678         ans = callrpc(hostname, pnum, 1, 1, xdr_void, 0,
2679                 xdr_void, 0);
2680         if (ans != 0) {
2681                 fprintf(stderr, "server: ");
2682                 clnt_perrno(ans);
2683                 fprintf(stderr, "\en");
2684         }
2685 }
2686 .vs
2687 .DE