1 /* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */ 2 /* 3 * Copyright (c) 2010, Oracle America, Inc. 4 * 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * * Neither the name of the "Oracle America, Inc." nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 28 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 #if !defined(lint) && defined(SCCSIDS) 35 static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; 36 #endif 37 38 /* 39 * pmap_prot2.c 40 * Protocol for the local binder service, or pmap. 41 */ 42 43 #include <gssrpc/types.h> 44 #include <gssrpc/xdr.h> 45 #include <gssrpc/pmap_prot.h> 46 47 48 /* 49 * What is going on with linked lists? (!) 50 * First recall the link list declaration from pmap_prot.h: 51 * 52 * struct pmaplist { 53 * struct pmap pml_map; 54 * struct pmaplist *pml_map; 55 * }; 56 * 57 * Compare that declaration with a corresponding xdr declaration that 58 * is (a) pointer-less, and (b) recursive: 59 * 60 * typedef union switch (bool_t) { 61 * 62 * case TRUE: struct { 63 * struct pmap; 64 * pmaplist_t foo; 65 * }; 66 * 67 * case FALSE: struct {}; 68 * } pmaplist_t; 69 * 70 * Notice that the xdr declaration has no nxt pointer while 71 * the C declaration has no bool_t variable. The bool_t can be 72 * interpreted as ``more data follows me''; if FALSE then nothing 73 * follows this bool_t; if TRUE then the bool_t is followed by 74 * an actual struct pmap, and then (recursively) by the 75 * xdr union, pamplist_t. 76 * 77 * This could be implemented via the xdr_union primitive, though this 78 * would cause a one recursive call per element in the list. Rather than do 79 * that we can ``unwind'' the recursion 80 * into a while loop and do the union arms in-place. 81 * 82 * The head of the list is what the C programmer wishes to past around 83 * the net, yet is the data that the pointer points to which is interesting; 84 * this sounds like a job for xdr_reference! 85 */ 86 bool_t 87 xdr_pmaplist(XDR *xdrs, struct pmaplist **rp) 88 { 89 /* 90 * more_elements is pre-computed in case the direction is 91 * XDR_ENCODE or XDR_FREE. more_elements is overwritten by 92 * xdr_bool when the direction is XDR_DECODE. 93 */ 94 bool_t more_elements; 95 int freeing = (xdrs->x_op == XDR_FREE); 96 struct pmaplist **next = NULL; 97 98 while (TRUE) { 99 more_elements = (bool_t)(*rp != NULL); 100 if (! xdr_bool(xdrs, &more_elements)) 101 return (FALSE); 102 if (! more_elements) 103 return (TRUE); /* we are done */ 104 /* 105 * the unfortunate side effect of non-recursion is that in 106 * the case of freeing we must remember the next object 107 * before we free the current object ... 108 */ 109 if (freeing) 110 next = &((*rp)->pml_next); 111 if (! xdr_reference(xdrs, (caddr_t *)rp, 112 (u_int)sizeof(struct pmaplist), xdr_pmap)) 113 return (FALSE); 114 rp = (freeing) ? next : &((*rp)->pml_next); 115 } 116 } 117