/* $NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ */12/*-3* SPDX-License-Identifier: BSD-3-Clause4*5* Copyright (c) 2009, Sun Microsystems, Inc.6* All rights reserved.7*8* Redistribution and use in source and binary forms, with or without9* modification, are permitted provided that the following conditions are met:10* - Redistributions of source code must retain the above copyright notice,11* this list of conditions and the following disclaimer.12* - Redistributions in binary form must reproduce the above copyright notice,13* this list of conditions and the following disclaimer in the documentation14* and/or other materials provided with the distribution.15* - Neither the name of Sun Microsystems, Inc. nor the names of its16* contributors may be used to endorse or promote products derived17* from this software without specific prior written permission.18*19* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"20* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE21* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE22* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE23* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR24* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF25* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS26* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN27* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE29* POSSIBILITY OF SUCH DAMAGE.30*/31/*32* Copyright (c) 1986-1991 by Sun Microsystems Inc.33*/3435#include <sys/cdefs.h>36/*37* rpcb_prot.c38* XDR routines for the rpcbinder version 3.39*40* Copyright (C) 1984, 1988, Sun Microsystems, Inc.41*/4243#include <sys/param.h>44#include <sys/systm.h>45#include <sys/kernel.h>46#include <sys/malloc.h>4748#include <rpc/rpc.h>49#include <rpc/rpc_com.h>50#include <rpc/rpcb_prot.h>5152bool_t53xdr_portmap(XDR *xdrs, struct portmap *regs)54{5556if (xdr_u_long(xdrs, ®s->pm_prog) &&57xdr_u_long(xdrs, ®s->pm_vers) &&58xdr_u_long(xdrs, ®s->pm_prot))59return (xdr_u_long(xdrs, ®s->pm_port));60return (FALSE);61}6263bool_t64xdr_rpcb(XDR *xdrs, RPCB *objp)65{66if (!xdr_uint32_t(xdrs, &objp->r_prog)) {67return (FALSE);68}69if (!xdr_uint32_t(xdrs, &objp->r_vers)) {70return (FALSE);71}72if (!xdr_string(xdrs, &objp->r_netid, RPC_MAXDATASIZE)) {73return (FALSE);74}75if (!xdr_string(xdrs, &objp->r_addr, RPC_MAXDATASIZE)) {76return (FALSE);77}78if (!xdr_string(xdrs, &objp->r_owner, RPC_MAXDATASIZE)) {79return (FALSE);80}81return (TRUE);82}8384/*85* rpcblist_ptr implements a linked list. The RPCL definition from86* rpcb_prot.x is:87*88* struct rpcblist {89* rpcb rpcb_map;90* struct rpcblist *rpcb_next;91* };92* typedef rpcblist *rpcblist_ptr;93*94* Recall that "pointers" in XDR are encoded as a boolean, indicating whether95* there's any data behind the pointer, followed by the data (if any exists).96* The boolean can be interpreted as ``more data follows me''; if FALSE then97* nothing follows the boolean; if TRUE then the boolean is followed by an98* actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct99* rpcblist *").100*101* This could be implemented via the xdr_pointer type, though this would102* result in one recursive call per element in the list. Rather than do that103* we can ``unwind'' the recursion into a while loop and use xdr_reference to104* serialize the rpcb elements.105*/106107bool_t108xdr_rpcblist_ptr(XDR *xdrs, rpcblist_ptr *rp)109{110/*111* more_elements is pre-computed in case the direction is112* XDR_ENCODE or XDR_FREE. more_elements is overwritten by113* xdr_bool when the direction is XDR_DECODE.114*/115bool_t more_elements;116int freeing = (xdrs->x_op == XDR_FREE);117rpcblist_ptr next;118rpcblist_ptr next_copy;119120next = NULL;121for (;;) {122more_elements = (bool_t)(*rp != NULL);123if (! xdr_bool(xdrs, &more_elements)) {124return (FALSE);125}126if (! more_elements) {127return (TRUE); /* we are done */128}129/*130* the unfortunate side effect of non-recursion is that in131* the case of freeing we must remember the next object132* before we free the current object ...133*/134if (freeing && *rp)135next = (*rp)->rpcb_next;136if (! xdr_reference(xdrs, (caddr_t *)rp,137(u_int)sizeof (RPCBLIST), (xdrproc_t)xdr_rpcb)) {138return (FALSE);139}140if (freeing) {141next_copy = next;142rp = &next_copy;143/*144* Note that in the subsequent iteration, next_copy145* gets nulled out by the xdr_reference146* but next itself survives.147*/148} else if (*rp) {149rp = &((*rp)->rpcb_next);150}151}152/*NOTREACHED*/153}154155#if 0156/*157* xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in158* functionality to xdr_rpcblist_ptr().159*/160bool_t161xdr_rpcblist(XDR *xdrs, RPCBLIST **rp)162{163bool_t dummy;164165dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);166return (dummy);167}168#endif169170bool_t171xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp)172{173if (!xdr_string(xdrs, &objp->r_maddr, RPC_MAXDATASIZE)) {174return (FALSE);175}176if (!xdr_string(xdrs, &objp->r_nc_netid, RPC_MAXDATASIZE)) {177return (FALSE);178}179if (!xdr_uint32_t(xdrs, &objp->r_nc_semantics)) {180return (FALSE);181}182if (!xdr_string(xdrs, &objp->r_nc_protofmly, RPC_MAXDATASIZE)) {183return (FALSE);184}185if (!xdr_string(xdrs, &objp->r_nc_proto, RPC_MAXDATASIZE)) {186return (FALSE);187}188return (TRUE);189}190191bool_t192xdr_rpcb_entry_list_ptr(XDR *xdrs, rpcb_entry_list_ptr *rp)193{194/*195* more_elements is pre-computed in case the direction is196* XDR_ENCODE or XDR_FREE. more_elements is overwritten by197* xdr_bool when the direction is XDR_DECODE.198*/199bool_t more_elements;200int freeing = (xdrs->x_op == XDR_FREE);201rpcb_entry_list_ptr next;202rpcb_entry_list_ptr next_copy;203204next = NULL;205for (;;) {206more_elements = (bool_t)(*rp != NULL);207if (! xdr_bool(xdrs, &more_elements)) {208return (FALSE);209}210if (! more_elements) {211return (TRUE); /* we are done */212}213/*214* the unfortunate side effect of non-recursion is that in215* the case of freeing we must remember the next object216* before we free the current object ...217*/218if (freeing)219next = (*rp)->rpcb_entry_next;220if (! xdr_reference(xdrs, (caddr_t *)rp,221(u_int)sizeof (rpcb_entry_list),222(xdrproc_t)xdr_rpcb_entry)) {223return (FALSE);224}225if (freeing && *rp) {226next_copy = next;227rp = &next_copy;228/*229* Note that in the subsequent iteration, next_copy230* gets nulled out by the xdr_reference231* but next itself survives.232*/233} else if (*rp) {234rp = &((*rp)->rpcb_entry_next);235}236}237/*NOTREACHED*/238}239240241