Fixed RPC code to deal with RPC messages larger than one mbuf. trunk
authorgwr <gwr@NetBSD.org>
Mon, 24 Apr 1995 21:54:56 +0000
branchtrunk
changeset 13477 3d0587d15459
parent 13476 9e6def1802b6
child 13478 7e3767cac0c2
Fixed RPC code to deal with RPC messages larger than one mbuf.
sys/nfs/krpc.h
sys/nfs/krpc_subr.c
sys/nfs/nfs_boot.c
--- a/sys/nfs/krpc.h	Mon Apr 24 21:34:04 1995 +0000
+++ b/sys/nfs/krpc.h	Mon Apr 24 21:54:56 1995 +0000
@@ -1,13 +1,18 @@
-/*	$NetBSD: krpc.h,v 1.2 1994/10/26 02:53:36 cgd Exp $	*/
+/*	$NetBSD: krpc.h,v 1.3 1995/04/24 21:54:56 gwr Exp $	*/
 
 #include <sys/cdefs.h>
 
 int krpc_call __P((struct sockaddr_in *sin, \
-	u_long prog, u_long vers, u_long func, \
+	u_int prog, u_int vers, u_int func, \
 	struct mbuf **data, struct mbuf **from));
 
 int krpc_portmap __P((struct sockaddr_in *sin, \
-	u_long prog, u_long vers, u_short *portp));
+	u_int prog, u_int vers, u_int16_t *portp));
+
+struct mbuf * xdr_string_encode __P((char *str, int len));
+struct mbuf * xdr_string_decode __P((struct mbuf *m, char *str, int *len_p));
+struct mbuf * xdr_inaddr_encode __P((struct in_addr *ia));
+struct mbuf * xdr_inaddr_decode __P((struct mbuf *m, struct in_addr *ia));
 
 
 /*
--- a/sys/nfs/krpc_subr.c	Mon Apr 24 21:34:04 1995 +0000
+++ b/sys/nfs/krpc_subr.c	Mon Apr 24 21:54:56 1995 +0000
@@ -1,7 +1,7 @@
-/*	$NetBSD: krpc_subr.c,v 1.7 1994/09/26 16:42:31 gwr Exp $	*/
+/*	$NetBSD: krpc_subr.c,v 1.8 1995/04/24 21:55:05 gwr Exp $	*/
 
 /*
- * Copyright (c) 1994 Gordon Ross, Adam Glass 
+ * Copyright (c) 1995 Gordon Ross, Adam Glass
  * Copyright (c) 1992 Regents of the University of California.
  * All rights reserved.
  *
@@ -43,14 +43,15 @@
  */
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/conf.h>
 #include <sys/ioctl.h>
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/mbuf.h>
+#include <sys/reboot.h>
 #include <sys/socket.h>
-#include <sys/systm.h>
-#include <sys/reboot.h>
+#include <sys/socketvar.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -62,9 +63,6 @@
  * Kernel support for Sun RPC
  *
  * Used currently for bootstrapping in nfs diskless configurations.
- * 
- * Note: will not work on variable-sized rpc args/results.
- *       implicit size-limit of an mbuf.
  */
 
 /*
@@ -72,30 +70,30 @@
  */
 
 struct auth_info {
-	int	rp_atype;		/* auth type */
-	u_long	rp_alen;		/* auth length */
+	int32_t	rp_atype;		/* auth type */
+	u_int32_t	rp_alen;	/* auth length */
 };
 
 struct rpc_call {
-	u_long	rp_xid;			/* request transaction id */
-	int 	rp_direction;	        /* call direction (0) */
-	u_long	rp_rpcvers;		/* rpc version (2) */
-	u_long	rp_prog;		/* program */
-	u_long	rp_vers;		/* version */
-	u_long	rp_proc;		/* procedure */
+	u_int32_t	rp_xid;		/* request transaction id */
+	int32_t 	rp_direction;	/* call direction (0) */
+	u_int32_t	rp_rpcvers;	/* rpc version (2) */
+	u_int32_t	rp_prog;	/* program */
+	u_int32_t	rp_vers;	/* version */
+	u_int32_t	rp_proc;	/* procedure */
 	struct	auth_info rp_auth;
 	struct	auth_info rp_verf;
 };
 
 struct rpc_reply {
-	u_long	rp_xid;			/* request transaction id */
-	int	rp_direction;		/* call direction (1) */
-	int	rp_astatus;		/* accept status (0: accepted) */
+	u_int32_t	rp_xid;		/* request transaction id */
+	int32_t 	rp_direction;	/* call direction (1) */
+	int32_t 	rp_astatus;	/* accept status (0: accepted) */
 	union {
-		u_long	rpu_errno;
+		u_int32_t	rpu_errno;
 		struct {
 			struct auth_info rp_auth;
-			u_long	rp_rstatus;		/* reply status */
+			u_int32_t	rp_rstatus;	/* reply status */
 		} rpu_ok;
 	} rp_u;
 };
@@ -117,18 +115,18 @@
 int
 krpc_portmap(sin,  prog, vers, portp)
 	struct sockaddr_in *sin;		/* server address */
-	u_long prog, vers;	/* host order */
-	u_short *portp;		/* network order */
+	u_int prog, vers;	/* host order */
+	u_int16_t *portp;		/* network order */
 {
 	struct sdata {
-		u_long	prog;		/* call program */
-		u_long	vers;		/* call version */
-		u_long	proto;		/* call protocol */
-		u_long	port;		/* call port (unused) */
+		u_int32_t	prog;		/* call program */
+		u_int32_t	vers;		/* call version */
+		u_int32_t	proto;		/* call protocol */
+		u_int32_t	port;		/* call port (unused) */
 	} *sdata;
 	struct rdata {
-		u_short pad;
-		u_short port;
+		u_int16_t pad;
+		u_int16_t port;
 	} *rdata;
 	struct mbuf *m;
 	int error;
@@ -139,12 +137,11 @@
 		return 0;
 	}
 
-	m = m_gethdr(M_WAIT, MT_DATA);
+	m = m_get(M_WAIT, MT_DATA);
 	if (m == NULL)
 		return ENOBUFS;
+	sdata = mtod(m, struct sdata *);
 	m->m_len = sizeof(*sdata);
-	m->m_pkthdr.len = m->m_len;
-	sdata = mtod(m, struct sdata *);
 
 	/* Do the RPC to get it. */
 	sdata->prog = htonl(prog);
@@ -158,6 +155,11 @@
 	if (error) 
 		return error;
 
+	if (m->m_len < sizeof(*rdata)) {
+		m = m_pullup(m, sizeof(*rdata));
+		if (m == NULL)
+			return ENOBUFS;
+	}
 	rdata = mtod(m, struct rdata *);
 	*portp = rdata->port;
 
@@ -173,7 +175,7 @@
 int
 krpc_call(sa, prog, vers, func, data, from_p)
 	struct sockaddr_in *sa;
-	u_long prog, vers, func;
+	u_int prog, vers, func;
 	struct mbuf **data;	/* input/output */
 	struct mbuf **from_p;	/* output */
 {
@@ -184,8 +186,8 @@
 	struct rpc_reply *reply;
 	struct uio auio;
 	int error, rcvflg, timo, secs, len;
-	static u_long xid = ~0xFF;
-	u_short tport;
+	static u_int32_t xid = ~0xFF;
+	u_int tport;
 
 	/*
 	 * Validate address family.
@@ -267,31 +269,16 @@
 		goto out;
 	}
 	sin = mtod(nam, struct sockaddr_in *);
-	bcopy((caddr_t)sa, (caddr_t)sin, (nam->m_len = sa->sin_len));
+	bcopy((caddr_t)sa, (caddr_t)sin,
+		  (nam->m_len = sa->sin_len));
 
 	/*
 	 * Prepend RPC message header.
 	 */
-	m = *data;
-	*data = NULL;
-#ifdef	DIAGNOSTIC
-	if ((m->m_flags & M_PKTHDR) == 0)
-		panic("krpc_call: send data w/o pkthdr");
-	if (m->m_pkthdr.len < m->m_len)
-		panic("krpc_call: pkthdr.len not set");
-#endif
-	mhead = m_prepend(m, sizeof(*call), M_WAIT);
-	if (mhead == NULL) {
-		error = ENOBUFS;
-		goto out;
-	}
-	mhead->m_pkthdr.len += sizeof(*call);
-	mhead->m_pkthdr.rcvif = NULL;
-
-	/*
-	 * Fill in the RPC header
-	 */
+	mhead = m_gethdr(M_WAIT, MT_DATA);
+	mhead->m_next = *data;
 	call = mtod(mhead, struct rpc_call *);
+	mhead->m_len = sizeof(*call);
 	bzero((caddr_t)call, sizeof(*call));
 	xid++;
 	call->rp_xid = htonl(xid);
@@ -304,6 +291,18 @@
 	/* call->rp_verf = 0; */
 
 	/*
+	 * Setup packet header
+	 */
+	len = 0;
+	m = mhead;
+	while (m) {
+		len += m->m_len;
+		m = m->m_next;
+	}
+	mhead->m_pkthdr.len = len;
+	mhead->m_pkthdr.rcvif = NULL;
+
+	/*
 	 * Send it, repeatedly, until a reply is received,
 	 * but delay each re-send by an increasing amount.
 	 * If the delay hits the maximum, start complaining.
@@ -393,30 +392,18 @@
  gotreply:
 
 	/*
-	 * Pull as much as we can into first mbuf, to make
-	 * result buffer contiguous.  Note that if the entire
-	 * result won't fit into one mbuf, you're out of luck.
-	 * XXX - Should not rely on making the entire reply
-	 * contiguous (fix callers instead). -gwr
+	 * Get RPC reply header into first mbuf,
+	 * get its length, then strip it off.
 	 */
-#ifdef	DIAGNOSTIC
-	if ((m->m_flags & M_PKTHDR) == 0)
-		panic("krpc_call: received pkt w/o header?");
-#endif
-	len = m->m_pkthdr.len;
+	len = sizeof(*reply);
 	if (m->m_len < len) {
 		m = m_pullup(m, len);
 		if (m == NULL) {
 			error = ENOBUFS;
 			goto out;
 		}
-		reply = mtod(m, struct rpc_reply *);
 	}
-
-	/*
-	 * Strip RPC header
-	 */
-	len = sizeof(*reply);
+	reply = mtod(m, struct rpc_reply *);
 	if (reply->rp_u.rpu_ok.rp_auth.rp_atype != 0) {
 		len += ntohl(reply->rp_u.rpu_ok.rp_auth.rp_alen);
 		len = (len + 3) & ~3; /* XXX? */
@@ -437,3 +424,139 @@
 	soclose(so);
 	return error;
 }
+
+/*
+ * eXternal Data Representation routines.
+ * (but with non-standard args...)
+ */
+
+/*
+ * String representation for RPC.
+ */
+struct xdr_string {
+	u_int32_t len;		/* length without null or padding */
+	char data[4];	/* data (longer, of course) */
+    /* data is padded to a long-word boundary */
+};
+
+struct mbuf *
+xdr_string_encode(str, len)
+	char *str;
+	int len;
+{
+	struct mbuf *m;
+	struct xdr_string *xs;
+	int dlen;	/* padded string length */
+	int mlen;	/* message length */
+
+	dlen = (len + 3) & ~3;
+	mlen = dlen + 4;
+
+	m = m_get(M_WAIT, MT_DATA);
+	if (mlen > MLEN) {
+		if (mlen > MCLBYTES)
+			return(NULL);
+		MCLGET(m, M_WAIT);
+		if (m == NULL)
+			return NULL;
+	}
+	xs = mtod(m, struct xdr_string *);
+	m->m_len = mlen;
+	xs->len = htonl(len);
+	bcopy(str, xs->data, len);
+	return (m);
+}
+
+struct mbuf *
+xdr_string_decode(m, str, len_p)
+	struct mbuf *m;
+	char *str;
+	int *len_p;		/* bufsize - 1 */
+{
+	struct xdr_string *xs;
+	int mlen;	/* message length */
+	int slen;	/* string length */
+
+	if (m->m_len < 4) {
+		m = m_pullup(m, 4);
+		if (m == NULL)
+			return (NULL);
+	}
+	xs = mtod(m, struct xdr_string *);
+	slen = ntohl(xs->len);
+	mlen = 4 + ((slen + 3) & ~3);
+
+	if (slen > *len_p)
+		slen = *len_p;
+	m_copydata(m, 4, slen, str);
+	m_adj(m, mlen);
+
+	str[slen] = '\0';
+	*len_p = slen;
+
+	return (m);
+}
+
+
+/*
+ * Inet address in RPC messages
+ * (Note, really four ints, NOT chars.  Blech.)
+ */
+struct xdr_inaddr {
+	u_int32_t  atype;
+	int32_t	addr[4];
+};
+
+struct mbuf *
+xdr_inaddr_encode(ia)
+	struct in_addr *ia;		/* already in network order */
+{
+	struct mbuf *m;
+	struct xdr_inaddr *xi;
+	u_char *cp;
+	int32_t *ip;
+
+	m = m_get(M_WAIT, MT_DATA);
+	xi = mtod(m, struct xdr_inaddr *);
+	m->m_len = sizeof(*xi);
+	xi->atype = htonl(1);
+	ip = xi->addr;
+	cp = (u_char *)&ia->s_addr;
+	*ip++ = *cp++;
+	*ip++ = *cp++;
+	*ip++ = *cp++;
+	*ip++ = *cp++;
+
+	return (m);
+}
+
+struct mbuf *
+xdr_inaddr_decode(m, ia)
+	struct mbuf *m;
+	struct in_addr *ia;		/* already in network order */
+{
+	struct xdr_inaddr *xi;
+	u_char *cp;
+	int32_t *ip;
+
+	if (m->m_len < sizeof(*xi)) {
+		m = m_pullup(m, sizeof(*xi));
+		if (m == NULL)
+			return (NULL);
+	}
+	xi = mtod(m, struct xdr_inaddr *);
+	if (xi->atype != htonl(1)) {
+		ia->s_addr = INADDR_ANY;
+		goto out;
+	}
+	ip = xi->addr;
+	cp = (u_char *)&ia->s_addr;
+	*cp++ = *ip++;
+	*cp++ = *ip++;
+	*cp++ = *ip++;
+	*cp++ = *ip++;
+
+out:
+	m_adj(m, sizeof(*xi));
+	return (m);
+}
--- a/sys/nfs/nfs_boot.c	Mon Apr 24 21:34:04 1995 +0000
+++ b/sys/nfs/nfs_boot.c	Mon Apr 24 21:54:56 1995 +0000
@@ -1,7 +1,7 @@
-/*    $NetBSD: nfs_boot.c,v 1.15 1995/03/28 21:29:32 gwr Exp $ */
+/*    $NetBSD: nfs_boot.c,v 1.16 1995/04/24 21:55:08 gwr Exp $ */
 
 /*
- * Copyright (c) 1994 Adam Glass, Gordon Ross
+ * Copyright (c) 1995 Adam Glass, Gordon Ross
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,9 @@
 #include <sys/proc.h>
 #include <sys/mount.h>
 #include <sys/mbuf.h>
+#include <sys/reboot.h>
 #include <sys/socket.h>
-#include <sys/reboot.h>
+#include <sys/socketvar.h>
 
 #include <net/if.h>
 #include <net/route.h>
@@ -112,8 +113,7 @@
 	struct sockaddr_in *sin;
 	struct ifnet *ifp;
 	struct socket *so;
-	int error, len;
-	u_short port;
+	int error;
 
 	/*
 	 * Find an interface, rarp for its ip address, stuff it, the
@@ -278,51 +278,6 @@
 
 
 /*
- * Get an mbuf with the given length, and
- * initialize the pkthdr length field.
- */
-static struct mbuf *
-m_get_len(int msg_len)
-{
-	struct mbuf *m;
-	m = m_gethdr(M_WAIT, MT_DATA);
-	if (m == NULL)
-		return NULL;
-	if (msg_len > MHLEN) {
-		if (msg_len > MCLBYTES)
-			panic("nfs_boot: msg_len > MCLBYTES");
-		MCLGET(m, M_WAIT);
-		if (m == NULL)
-			return NULL;
-	}
-	m->m_len = msg_len;
-	m->m_pkthdr.len = m->m_len;
-	return (m);
-}
-
-
-/*
- * String representation for RPC.
- */
-struct rpc_string {
-	u_long len;		/* length without null or padding */
-	u_char data[4];	/* data (longer, of course) */
-    /* data is padded to a long-word boundary */
-};
-/* Compute space used given string length. */
-#define	RPC_STR_SIZE(slen) (4 + ((slen + 3) & ~3))
-
-/*
- * Inet address in RPC messages
- * (Note, really four longs, NOT chars.  Blech.)
- */
-struct bp_inaddr {
-	u_long  atype;
-	long	addr[4];
-};
-
-
-/*
  * RPC: bootparam/whoami
  * Given client IP address, get:
  *	client name	(hostname)
@@ -345,47 +300,37 @@
 {
 	/* RPC structures for PMAPPROC_CALLIT */
 	struct whoami_call {
-		u_long call_prog;
-		u_long call_vers;
-		u_long call_proc;
-		u_long call_arglen;
-		struct bp_inaddr call_ia;
+		u_int32_t call_prog;
+		u_int32_t call_vers;
+		u_int32_t call_proc;
+		u_int32_t call_arglen;
 	} *call;
+	struct callit_reply {
+		u_int32_t port;
+		u_int32_t encap_len;
+		/* encapsulated data here */
+	} *reply;
 
-	struct rpc_string *str;
-	struct bp_inaddr *bia;
 	struct mbuf *m, *from;
 	struct sockaddr_in *sin;
 	int error, msg_len;
-	int cn_len, dn_len;
-	u_char *p;
-	long *lp;
-
-	/*
-	 * Get message buffer of sufficient size.
-	 */
-	msg_len = sizeof(*call);
-	m = m_get_len(msg_len);
-	if (m == NULL)
-		return ENOBUFS;
+	int16_t port;
 
 	/*
 	 * Build request message for PMAPPROC_CALLIT.
 	 */
+	m = m_get(M_WAIT, MT_DATA);
 	call = mtod(m, struct whoami_call *);
+	m->m_len = sizeof(*call);
 	call->call_prog = htonl(BOOTPARAM_PROG);
 	call->call_vers = htonl(BOOTPARAM_VERS);
 	call->call_proc = htonl(BOOTPARAM_WHOAMI);
-	call->call_arglen = htonl(sizeof(struct bp_inaddr));
 
-	/* client IP address */
-	call->call_ia.atype = htonl(1);
-	p = (u_char*)my_ip;
-	lp = call->call_ia.addr;
-	*lp++ = htonl(*p);	p++;
-	*lp++ = htonl(*p);	p++;
-	*lp++ = htonl(*p);	p++;
-	*lp++ = htonl(*p);	p++;
+	/*
+	 * append encapsulated data (client IP address)
+	 */
+	m->m_next = xdr_inaddr_encode(my_ip);
+	call->call_arglen = m->m_next->m_len;
 
 	/* RPC: portmap/callit */
 	bpsin->sin_port = htons(PMAPPORT);
@@ -398,64 +343,41 @@
 	/*
 	 * Parse result message.
 	 */
-	msg_len = m->m_len;
-	lp = mtod(m, long *);
+	if (m->m_len < sizeof(*reply)) {
+		m = m_pullup(m, sizeof(*reply));
+		if (m == NULL)
+			goto bad;
+	}
+	reply = mtod(m, struct callit_reply *);
+	port = ntohl(reply->port);
+	msg_len = ntohl(reply->encap_len);
+	m_adj(m, sizeof(*reply));
 
-	/* bootparam server port (also grab from address). */
-	if (msg_len < sizeof(*lp))
-		goto bad;
-	msg_len -= sizeof(*lp);
-	bpsin->sin_port = htons((short)ntohl(*lp++));
+	/*
+	 * Save bootparam server address
+	 */
 	sin = mtod(from, struct sockaddr_in *);
+	bpsin->sin_port = htons(port);
 	bpsin->sin_addr.s_addr = sin->sin_addr.s_addr;
 
-	/* length of encapsulated results */
-	if (msg_len < (ntohl(*lp) + sizeof(*lp)))
-		goto bad;
-	msg_len = ntohl(*lp++);
-	p = (char*)lp;
-
 	/* client name */
-	if (msg_len < sizeof(*str))
-		goto bad;
-	str = (struct rpc_string *)p;
-	cn_len = ntohl(str->len);
-	if (msg_len < cn_len)
+	hostnamelen = MAXHOSTNAMELEN-1;
+	m = xdr_string_decode(m, hostname, &hostnamelen);
+	if (m == NULL)
 		goto bad;
-	if (cn_len >= MAXHOSTNAMELEN)
-		goto bad;
-	bcopy(str->data, hostname, cn_len);
-	hostname[cn_len] = '\0';
-	hostnamelen = cn_len;
-	p += RPC_STR_SIZE(cn_len);
-	msg_len -= RPC_STR_SIZE(cn_len);
 
 	/* domain name */
-	if (msg_len < sizeof(*str))
-		goto bad;
-	str = (struct rpc_string *)p;
-	dn_len = ntohl(str->len);
-	if (msg_len < dn_len)
+	domainnamelen = MAXHOSTNAMELEN-1;
+	m = xdr_string_decode(m, domainname, &domainnamelen);
+	if (m == NULL)
 		goto bad;
-	if (dn_len >= MAXHOSTNAMELEN)
-		goto bad;
-	bcopy(str->data, domainname, dn_len);
-	domainname[dn_len] = '\0';
-	domainnamelen = dn_len;
-	p += RPC_STR_SIZE(dn_len);
-	msg_len -= RPC_STR_SIZE(dn_len);
 
 	/* gateway address */
-	if (msg_len < sizeof(*bia))
-		goto bad;
-	bia = (struct bp_inaddr *)p;
-	if (bia->atype != htonl(1))
+	m = xdr_inaddr_decode(m, gw_ip);
+	if (m == NULL)
 		goto bad;
-	p = (u_char*)gw_ip;
-	*p++ = ntohl(bia->addr[0]);
-	*p++ = ntohl(bia->addr[1]);
-	*p++ = ntohl(bia->addr[2]);
-	*p++ = ntohl(bia->addr[3]);
+
+	/* success */
 	goto out;
 
 bad:
@@ -465,7 +387,8 @@
 out:
 	if (from)
 		m_freem(from);
-	m_freem(m);
+	if (m)
+		m_freem(m);
 	return(error);
 }
 
@@ -485,40 +408,20 @@
 	char *serv_name;
 	char *pathname;
 {
-	struct rpc_string *str;
 	struct mbuf *m;
-	struct bp_inaddr *bia;
 	struct sockaddr_in *sin;
-	u_char *p, *q;
-	int error, msg_len;
-	int cn_len, key_len, sn_len, path_len;
-
-	/*
-	 * Get message buffer of sufficient size.
-	 */
-	cn_len = hostnamelen;
-	key_len = strlen(key);
-	msg_len = 0;
-	msg_len += RPC_STR_SIZE(cn_len);
-	msg_len += RPC_STR_SIZE(key_len);
-	m = m_get_len(msg_len);
-	if (m == NULL)
-		return ENOBUFS;
+	struct in_addr inaddr;
+	int error, sn_len, path_len;
 
 	/*
 	 * Build request message.
 	 */
-	p = mtod(m, u_char *);
-	bzero(p, msg_len);
+
 	/* client name (hostname) */
-	str = (struct rpc_string *)p;
-	str->len = htonl(cn_len);
-	bcopy(hostname, str->data, cn_len);
-	p += RPC_STR_SIZE(cn_len);
+	m  = xdr_string_encode(hostname, hostnamelen);
+
 	/* key name (root or swap) */
-	str = (struct rpc_string *)p;
-	str->len = htonl(key_len);
-	bcopy(key, str->data, key_len);
+	m->m_next = xdr_string_encode(key, strlen(key));
 
 	/* RPC: bootparam/getfile */
 	error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS,
@@ -529,52 +432,32 @@
 	/*
 	 * Parse result message.
 	 */
-	p = mtod(m, u_char *);
-	msg_len = m->m_len;
 
 	/* server name */
-	if (msg_len < sizeof(*str))
+	sn_len = MNAMELEN-1;
+	m = xdr_string_decode(m, serv_name, &sn_len);
+	if (m == NULL)
 		goto bad;
-	str = (struct rpc_string *)p;
-	sn_len = ntohl(str->len);
-	if (msg_len < sn_len)
-		goto bad;
-	if (sn_len >= MNAMELEN)
+
+	/* server IP address (mountd/NFS) */
+	m = xdr_inaddr_decode(m, &inaddr);
+	if (m == NULL)
 		goto bad;
-	bcopy(str->data, serv_name, sn_len);
-	serv_name[sn_len] = '\0';
-	p += RPC_STR_SIZE(sn_len);
-	msg_len -= RPC_STR_SIZE(sn_len);
 
-	/* server IP address (mountd) */
-	if (msg_len < sizeof(*bia))
+	/* server pathname */
+	path_len = MAXPATHLEN-1;
+	m = xdr_string_decode(m, pathname, &path_len);
+	if (m == NULL)
 		goto bad;
-	bia = (struct bp_inaddr *)p;
-	if (bia->atype != htonl(1))
-		goto bad;
+
+	/* setup server socket address */
 	sin = md_sin;
 	bzero((caddr_t)sin, sizeof(*sin));
 	sin->sin_len = sizeof(*sin);
 	sin->sin_family = AF_INET;
-	q = (u_char*) &sin->sin_addr;
-	*q++ = ntohl(bia->addr[0]);
-	*q++ = ntohl(bia->addr[1]);
-	*q++ = ntohl(bia->addr[2]);
-	*q++ = ntohl(bia->addr[3]);
-	p += sizeof(*bia);
-	msg_len -= sizeof(*bia);
+	sin->sin_addr = inaddr;
 
-	/* server pathname */
-	if (msg_len < sizeof(*str))
-		goto bad;
-	str = (struct rpc_string *)p;
-	path_len = ntohl(str->len);
-	if (msg_len < path_len)
-		goto bad;
-	if (path_len >= MAXPATHLEN)
-		goto bad;
-	bcopy(str->data, pathname, path_len);
-	pathname[path_len] = '\0';
+	/* success */
 	goto out;
 
 bad:
@@ -599,28 +482,19 @@
 	u_char *fhp;
 {
 	/* The RPC structures */
-	struct rpc_string *str;
 	struct rdata {
-		u_long	errno;
+		u_int32_t	errno;
 		u_char	fh[NFS_FHSIZE];
 	} *rdata;
 	struct mbuf *m;
-	int error, mlen, slen;
+	int error;
 
 	/* Get port number for MOUNTD. */
 	error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
 						 &mdsin->sin_port);
 	if (error) return error;
 
-	slen = strlen(path);
-	mlen = RPC_STR_SIZE(slen);
-
-	m = m_get_len(mlen);
-	if (m == NULL)
-		return ENOBUFS;
-	str = mtod(m, struct rpc_string *);
-	str->len = htonl(slen);
-	bcopy(path, str->data, slen);
+	m = xdr_string_encode(path, strlen(path));
 
 	/* Do RPC to mountd. */
 	error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
@@ -628,9 +502,11 @@
 	if (error)
 		return error;	/* message already freed */
 
-	mlen = m->m_len;
-	if (mlen < sizeof(*rdata))
-		goto bad;
+	if (m->m_len < sizeof(*rdata)) {
+		m = m_pullup(m, sizeof(*rdata));
+		if (m == NULL)
+			goto bad;
+	}
 	rdata = mtod(m, struct rdata *);
 	error = ntohl(rdata->errno);
 	if (error)