]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/krpc_subr.c
xnu-4570.61.1.tar.gz
[apple/xnu.git] / bsd / nfs / krpc_subr.c
index f342ae47611d6e49a5f065a384b0325d47499447..7ae7758e00307a0d5eebba6e28ccb5f12351aa82 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * unlawful or unlicensed copies of an Apple operating system, or to
  * circumvent, violate, or enable the circumvention or violation of, any
  * terms of an Apple operating system software license agreement.
- * 
+ *
  * Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
 /*
- * Copyright (c) 1994 Gordon Ross, Adam Glass 
+ * Copyright (c) 1994 Gordon Ross, Adam Glass
  * Copyright (c) 1992 Regents of the University of California.
  * All rights reserved.
  *
@@ -76,7 +76,6 @@
 #include <sys/socketvar.h>
 #include <sys/systm.h>
 #include <sys/reboot.h>
-#include <sys/uio_internal.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
@@ -127,6 +126,7 @@ struct rpc_reply {
 };
 
 #define MIN_REPLY_HDR 16       /* xid, dir, astat, errno */
+#define REPLY_SIZE 24          /* xid, dir, astat, rpu_ok */
 
 /*
  * What is the longest we will wait before re-sending a request?
@@ -147,10 +147,10 @@ struct rpc_reply {
  * Returns non-zero error on failure.
  */
 int
-krpc_portmap(sin, prog, vers, proto, portp)
-       struct sockaddr_in *sin;        /* server address */
-       u_int prog, vers, proto;        /* host order */
-       u_int16_t *portp;               /* network order */
+krpc_portmap(
+       struct sockaddr_in *sin,        /* server address */
+       u_int prog, u_int vers, u_int proto,    /* host order */
+       u_int16_t *portp)               /* network order */
 {
        struct sdata {
                u_int32_t prog;         /* call program */
@@ -190,9 +190,12 @@ krpc_portmap(sin, prog, vers, proto, portp)
                return error;
 
        rdata = mbuf_data(m);
-       *portp = rdata->port;
 
-       if (!rdata->port)
+       if (mbuf_len(m) >= sizeof(*rdata)) {
+               *portp = rdata->port;
+       }
+
+       if (mbuf_len(m) < sizeof(*rdata) || !rdata->port)
                error = EPROGUNAVAIL;
 
        mbuf_freem(m);
@@ -205,21 +208,22 @@ krpc_portmap(sin, prog, vers, proto, portp)
  * the address from whence the response came is saved there.
  */
 int
-krpc_call(sa, sotype, prog, vers, func, data, from_p)
-       struct sockaddr_in *sa;
-       u_int sotype, prog, vers, func;
-       mbuf_t *data;                   /* input/output */
-       struct sockaddr_in *from_p;     /* output */
+krpc_call(
+       struct sockaddr_in *sa,
+       u_int sotype, u_int prog, u_int vers, u_int func,
+       mbuf_t *data,                   /* input/output */
+       struct sockaddr_in *from_p)     /* output */
 {
        socket_t so;
        struct sockaddr_in *sin;
        mbuf_t m, nam, mhead;
        struct rpc_call *call;
        struct rpc_reply *reply;
-       int error, timo, secs, len;
+       int error, timo, secs;
+       size_t len;
        static u_int32_t xid = ~0xFF;
        u_int16_t tport;
-       int maxpacket = 1<<16;
+       size_t maxpacket = 1<<16;
 
        /*
         * Validate address family.
@@ -235,7 +239,7 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
         * Create socket and set its recieve timeout.
         */
        if ((error = sock_socket(AF_INET, sotype, 0, 0, 0, &so)))
-               goto out;
+               goto out1;
 
        {
                struct timeval tv;
@@ -335,7 +339,7 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
         */
        if (sotype == SOCK_STREAM) {
                /* first, fill in RPC record marker */
-               u_long *recmark = mbuf_data(mhead);
+               u_int32_t *recmark = mbuf_data(mhead);
                *recmark = htonl(0x80000000 | (mbuf_pkthdr_len(mhead) - 4));
                call = (struct rpc_call *)(recmark + 1);
        } else {
@@ -400,11 +404,11 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
                        }
                        if (sotype == SOCK_STREAM) {
                                int maxretries = 60;
-                               struct iovec_32 aio;
-                               aio.iov_base = (uintptr_t) &len;
-                               aio.iov_len = sizeof(u_long);
+                               struct iovec aio;
+                               aio.iov_base = &len;
+                               aio.iov_len = sizeof(u_int32_t);
                                bzero(&msg, sizeof(msg));
-                               msg.msg_iov = (struct iovec *) &aio;
+                               msg.msg_iov = &aio;
                                msg.msg_iovlen = 1;
                                do {
                                   error = sock_receive(so, &msg, MSG_WAITALL, &readlen);
@@ -414,8 +418,8 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
                                if (!error && readlen < aio.iov_len) {
                                    /* only log a message if we got a partial word */
                                    if (readlen != 0)
-                                           printf("short receive (%d/%d) from server " IP_FORMAT "\n",
-                                                readlen, sizeof(u_long), IP_LIST(&(sin->sin_addr.s_addr)));
+                                           printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
+                                                readlen, sizeof(u_int32_t), IP_LIST(&(sin->sin_addr.s_addr)));
                                    error = EPIPE;
                                }
                                if (error)
@@ -426,7 +430,7 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
                                 * and forcing a disconnect/reconnect is all I can do.
                                 */
                                if (len > maxpacket) {
-                                   printf("impossible packet length (%d) from server %s\n",
+                                   printf("impossible packet length (%ld) from server " IP_FORMAT "\n",
                                        len, IP_LIST(&(sin->sin_addr.s_addr)));
                                    error = EFBIG;
                                    goto out;
@@ -437,8 +441,8 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
                                    error = sock_receivembuf(so, NULL, &m, MSG_WAITALL, &readlen);
                                } while (error == EWOULDBLOCK);
 
-                               if (!error && (len > (int)readlen)) {
-                                   printf("short receive (%d/%d) from server %s\n",
+                               if (!error && (len > readlen)) {
+                                   printf("short receive (%ld/%ld) from server " IP_FORMAT "\n",
                                        readlen, len, IP_LIST(&(sin->sin_addr.s_addr)));
                                    error = EPIPE;
                                }
@@ -489,8 +493,16 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
                                goto out;
                        }
 
+
+                       if (mbuf_len(m) < REPLY_SIZE) {
+                               error = RPC_SYSTEM_ERR;
+                       }
+                       else {
+                               error = ntohl(reply->rp_u.rpu_ok.rp_rstatus);
+                       }
+
                        /* Did the call succeed? */
-                       if ((error = ntohl(reply->rp_u.rpu_ok.rp_rstatus)) != 0) {
+                       if (error != 0) {
                                printf("rpc status=%d\n", error);
                                /* convert rpc error to errno */
                                switch (error) {
@@ -556,8 +568,9 @@ krpc_call(sa, sotype, prog, vers, func, data, from_p)
        /* result */
        *data = m;
  out:
+       sock_close(so);
+out1:
        if (nam) mbuf_freem(nam);
        if (mhead) mbuf_freem(mhead);
-       sock_close(so);
        return error;
 }