Homework 5, Due at the beginning of class, Thursday, May22nd.
Internet and Linux online information on RPC. Some useful sites:
Current standardization state of ONC RPC
In the following, you will create a rudimentary distributed Public Key Infrastructure (PKI) server using remote procedure calls (RPC).
Step 1) A sample key server program which allows for the creation and editing of a dictionary of keys is provided. This program is designed to run on a single computer. In the following steps, you will use RPC procedures to turn it into a distributed program. Compile the dict.c program provided into dict. Run and verify operation. The idea is that keys will be added in the form of "user,key". Keys can be inserted and deleted using the "i" and "d" options. Keys can be retrieved using the l "user" function. The key database can be initialized with the "I" command.
Step 2) Divide the dict.c program into client and server components. One component, which will contain the user interface, will become the client, the other part will consist of the procedures to be run on the server. Since the point of our cryptographic key dictionary server is to store the keys in a central, network accessible location, the data and data manipulation procedures should be in the server component. Don't add any additional code at this point, just divide what is provided. Test that your two modules are still semantically correct by compiling them, as in cc -c rdict.c and cc -c rdictd.c. (However, do not try to link them since they are not complete programs.)
Step 3) Create an rpcgen specification. The specification will be in a file named rdict.x, and consist of the following sections: a) a constant declaration for the constants used in the dict program. Obvious constants are the maxkey and dictsiz. The form is "const maxkey = 80" b) Declaration of data types used, especially in the args to remote procedures. c) The definitions of the procedures which will be called remotely and their parameters. See rpcgen documentation for details and samples.
Step 4) Run rpcgen on dict.x. If your specification is correct, rpcgen will produce a header file, rdict.h, an XDR conversion file rdict_xdr.c, a client side communication program rdict_clnt.c, and a server side communication program rdict.svc. Take a look at the files.
Step 5) Write the client side interface Routines. For each procedure that has been moved to the server side, create a "stub" procedure which has the same name, argument and same return as the original procedure, but which calls the corresponding client side communication procedure. For example, insertw in the original program accepts a pointer to a string, so your stub interface should be named insertw, accept a pointer to a string and call insertw_l, the client side communication stub generated by rpcgen.
The major difference with the rpcgen code is that indirection is used. For example, if the original procedure had an integer argument, the corresponding argument in the communication stub for that procedure must be a pointer to an integer. The character string pointers in the dictionary program (char *) will become a pointer to a character pointer (char **)
Use the name rdict_cif.c, if you want to use the Makefile I provide. Your client stub code will need an external reference to the rpc handle, so a declaration like
extern CLIENT *handle;
Step 6) A few lines of code need to be added to the original client code, rdict.c:
Compile the client.
Step 7) Write the server side interface routines in the same fashion as the client side interfaces in (5). Use the name rdict_sif.c to match the makefile. Add the includes from (6) to the server code from the original program rdictd.c (you don't need the define or handle)
Compile the server.
Step 8) Run the server ( >rdictd & ) and run the client (> rdict ) against it on the same machine to verify operation.
Change the host specification from "localhost" to a different linux machines, recompile and test with the server on one machine and the client on another. Try putting one component on one of the department's solaris machines. (a solaris machine, such as urania, will have return true from the command "sparc")
Step 9) Once the program is built in distributed mode, the modules can still be changed. For example, my lookup routine is not very careful about how it matches user names. Fix the user name matching to be more precise.
Deliverables: turn in a typescript from a linux and sparc machine run of the client against a single server, along with the source code. Also email a copy of the source code to Ted. Indicate the machine you are on in your typescript so Ted can verify both sparc and linux.
Note that the next and final programming assignment will consist of extending either this RPC base, or the web server base code into more extensive systems. There will be a choice of several options. If you want to get a start on this by adding actual public key crypto routines to rdict to turn it into an actual key server, you may do so.
Have your server save entries to a file so that on the next invocation, it will have not lost the entries from the last time is was run. Rathing than doing this with traditional file read/write, use the mmap() system call to map your string memory to a file. This way the operating system virtual memory managmeent system will do all of your I/O for you. (That is what happens in the Linux kernel anyhow.) To implement this, on initial startup, run the mmap and on exit unmap the file. No other action needs to be taken