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