home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume13 / rpc3.9 / part11 / doc / rpc.prog.ms
Encoding:
Text File  |  1988-02-27  |  61.5 KB  |  2,491 lines

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