next up previous contents
Next: XDR functions Up: API Versioning Previous: Header file declarations   Contents

Server library functions

Server library functions must know how many and what type of arguments to expect, and must operate on those arguments correctly, based on the API version with which they are invoked. The API version is contained in the handle that is alwasy passed as their first argument, generated by kadm5_init_* (to which the client specified the API version to use at run-time).

In general, it is probably unsafe for a compiled function in a library to re-interpret the number and type of defined arguments at run-time since the calling conventions may not allow it; for example, a function whose first argument was a short in one version and a pointer in the next might fail if it simply typed-casted the argument. In that case, the function would have to written to take variable arguments (i.e. use $<$stdarg.h$>$) and extract them from the stack based on the API version. Alternatively, a separate function for each API version could be defined, and $<$kadm5/admin.h$>$ could be written to #1 the exported function name based on the value of USE_KADM5_API_VERSION.

In the current system, it turns out, that isn't necessary, and future implementors should take try to ensure that no version has semantics that will cause such problems in the future. All the functions in KADM5 that have different arguments or results between VERSION_1 and VERSION_2 do so simply by type-casting their arguments to the appropriate version and then have separate code paths to handle each one correctly. kadm5_get_principal, in svr_principal.c, is a good example. In VERSION_1, it took the address of a pointer to a kadm5_principal_ent_t to fill in with a pointer to allocated memory; in VERSION_2, it takes a pointer to a structure to fill in, and a mask of which fields in that structure should be filled in. Also, the contents of the kadm5_principal_ent_t changed slightly between the two versions. kadm5_get_principal handles versioning as follows (following along in the source code will be helpful):

  1. If VERSION_1, it saves away its entry argument (address of a pointer to a structure) and resets its value to contain the address of a locally stack-allocated entry structure; this allows most of the function to written once, in terms of VERSION_2 semantics. If VERSION_1, it also resets its mask argument to be KADM5_PRINCIPAL_NORMAL_MASK, because that is the equivalent to VERSION_1 behavior, which was to return all the fields of the structure.

  2. The bulk of the function is implemented as expected for VERSION_2.

  3. The new fields in the VERSION_2 entry structure are assigned inside a block that is only execute if the caller specified VERSION_2. This saves a little time for a VERSION_1 caller.

  4. After the entry structure is filled, the function checks again if it was called as VERSION_1. If so, it allocates a new kadm5_principal_ent_t_v1 structure (which is conveniently defined in the header file) with malloc, copies the appropriate values from the entry structure into the VERSION_1 entry structure, and then writes the address of the newly allocated memory into address specified by the original entry argument which it had previously saved away.

There is another complication involved in a function re-interpreting the number of arguments it receives at compile time--it cannot assign any value to an argument for which the client did not pass a value. For example, a VERSION_1 client only passes three arguments to kadm5_get_principal. If the implementation of kadm5_get_principal notices that the caller is VERSION_1 and therefore assigns its fourth argument, mask, to a value that mimics the VERSION_1 behavior, it may inadvertently overwrite data on its caller's stack. This problem can be avoided simply by using a true local variable in such cases, instead of treating an unpassed argument as a local variable.


next up previous contents
Next: XDR functions Up: API Versioning Previous: Header file declarations   Contents
Autobuild 2006-06-16