home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / lib / librpc / doc / rpc.prog.ms < prev    next >
Encoding:
Text File  |  1989-07-11  |  67.2 KB  |  2,685 lines

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