]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/asp_proto.c
xnu-792.6.56.tar.gz
[apple/xnu.git] / bsd / netat / asp_proto.c
index c495412dea3577535ef144ab3b2db0bb8a7b7932..79330c5427c02da1b2b370a84b9d767d7ceb91c4 100644 (file)
@@ -3,19 +3,20 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_LICENSE_HEADER_END@
  */
@@ -40,6 +41,7 @@
 #include <sys/mbuf.h>
 #include <sys/ioctl.h>
 #include <sys/malloc.h>
+#include <kern/locks.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
@@ -81,11 +83,10 @@ void asp_init();
 void asp_ack_reply();
 void asp_nak_reply();
 void asp_clock();
-void asp_clock_funnel();
+void asp_clock_locked(void *);
 int  asp_open();
 int  asp_close();
 int  asp_wput();
-void atp_retry_req();
 StaticProc asp_scb_t *asp_find_scb();
 StaticProc asp_scb_t *asp_scb_alloc();
 
@@ -98,13 +99,14 @@ StaticProc void asp_timout();
 StaticProc void asp_untimout();
 StaticProc void asp_hangup();
 StaticProc void asp_send_tickle();
-StaticProc void asp_send_tickle_funnel();
+StaticProc void asp_send_tickle_locked(void *);
 StaticProc void asp_accept();
 StaticProc int  asp_send_req();
 
 extern at_ifaddr_t *ifID_home;
 extern int atp_pidM[];
 extern gref_t *atp_inputQ[];
+extern lck_mtx_t *atalk_mutex;
 gbuf_t *scb_resource_m = 0;
 unsigned char asp_inpC[256];
 asp_scb_t *asp_scbQ[256];
@@ -266,7 +268,7 @@ asp_close(gref)
         */
        scb->tmo_cnt = 0;
        asp_untimout(asp_hangup, scb);
-       untimeout(asp_send_tickle_funnel, (void *)scb); /* added for 2225395 */
+       untimeout(asp_send_tickle_locked, (void *)scb); /* added for 2225395 */
 
        /*
         * free the asp session control block
@@ -371,7 +373,7 @@ void trace_end(str)
        dPrintf(D_M_ASP, D_L_TRACE,
                ("  %s: %s\n", str, mbuf_totals()));
 }
-#endif AT_MBUF_TRACE
+#endif /* AT_MBUF_TRACE */
 
 /*
  * the write routine
@@ -494,7 +496,7 @@ int asp_wput(gref, m)
 
        case ASPIOC_GetLocEntity:
                if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
-                       asp_iocnak(gref, mioc, EPROTO);
+                       asp_iocnak(gref, mioc, EPROTOTYPE);
                        return 0;
                }
                *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->loc_addr;
@@ -502,7 +504,7 @@ int asp_wput(gref, m)
 
        case ASPIOC_GetRemEntity:
                if ((gbuf_cont(mioc) == 0) || (scb->atp_state == 0)) {
-                       asp_iocnak(gref, mioc, EPROTO);
+                       asp_iocnak(gref, mioc, EPROTOTYPE);
                        return 0;
                }
                *(at_inet_t *)gbuf_rptr(gbuf_cont(mioc)) = scb->rem_addr;
@@ -510,7 +512,7 @@ int asp_wput(gref, m)
 
        case ASPIOC_GetSession:
                if ((mdata = gbuf_cont(mioc)) == 0) {
-                       asp_iocnak(gref, mioc, EPROTO);
+                       asp_iocnak(gref, mioc, EPROTOTYPE);
                        return 0;
                }
                addr = (at_inet_t *)gbuf_rptr(mdata);
@@ -519,11 +521,11 @@ int asp_wput(gref, m)
                server_scb = asp_scbQ[addr->socket];
 /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */
                if (server_scb == 0) {
-                       asp_iocnak(gref, mioc, EPROTO);
+                       asp_iocnak(gref, mioc, EPROTOTYPE);
                        return 0;
                }
                if (server_scb->sess_ioc == 0) {
-                       asp_iocnak(gref, mioc, EPROTO);
+                       asp_iocnak(gref, mioc, EPROTOTYPE);
                        return 0;
                }
 
@@ -659,7 +661,7 @@ int asp_wput(gref, m)
                {
                struct atp_state *atp = (struct atp_state *)gref->info;
                if (atp->dflag)
-                       atp = atp->atp_msgq;
+                       atp = (struct atp_state *)atp->atp_msgq;
                                        
                if (gbuf_cont(mioc) == 0) {
                        asp_iocnak(gref, mioc, EINVAL);
@@ -775,15 +777,15 @@ asp_send_req(gref, mioc, dest, retry, awp, xo, state, bitmap)
 }
 
 /*
- * send tickle routine - funnelled version
+ * send tickle routine - locked version
  */
 StaticProc void
-asp_send_tickle_funnel(scb)
-       asp_scb_t *scb;
+asp_send_tickle_locked(scb)
+       void *scb;
 {
-        thread_funnel_set(network_flock, TRUE);
-       asp_send_tickle(scb);
-        thread_funnel_set(network_flock, FALSE);
+       atalk_lock();
+       asp_send_tickle((asp_scb_t *)scb);
+       atalk_unlock();
 }
 
 
@@ -811,7 +813,7 @@ asp_send_tickle(scb)
                dPrintf(D_M_ASP, D_L_WARNING,
                ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n",
                        scb->loc_addr.socket,scb->rem_addr.socket));
-               timeout(asp_send_tickle_funnel, (void *)scb, 10);
+               timeout(asp_send_tickle_locked, (void *)scb, 10);
                return;
        }
        gbuf_wset(mioc,sizeof(ioc_t));
@@ -833,7 +835,7 @@ asp_send_tickle(scb)
                        ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n",
                         scb->loc_addr.socket,scb->rem_addr.socket));
 
-               timeout(asp_send_tickle_funnel, (void *)scb, 10);
+               timeout(asp_send_tickle_locked, (void *)scb, 10);
                return;
        }
 }
@@ -894,14 +896,14 @@ asp_accept(scb, sess_scb, m)
 } /* asp_accept */
 
 /*
- * timer routine - funneled version
+ * timer routine - locked version
  */
-void asp_clock_funnel(arg)
+void asp_clock_locked(arg)
        void *arg;
 {
-        thread_funnel_set(network_flock, TRUE);
+       atalk_lock();
        asp_clock(arg);
-        thread_funnel_set(network_flock, FALSE);
+       atalk_unlock();
 }
 
 /*
@@ -930,7 +932,7 @@ void asp_clock(arg)
        ATENABLE(s, asptmo_lock);
 
        if (++scb_tmo_cnt == 0) scb_tmo_cnt++;
-       timeout(asp_clock_funnel, (void *)arg, (1<<SESS_TMO_RES)*TICKS_PER_SEC);
+       timeout(asp_clock_locked, (void *)arg, (1<<SESS_TMO_RES)*TICKS_PER_SEC);
         
 }
 
@@ -1521,7 +1523,7 @@ asp_nak_reply(gref, mioc)
 
                        /* last remaining use of MSG_ERROR */
                        gbuf_set_type(mioc, MSG_ERROR);
-                       *gbuf_rptr(mioc) = (u_char)EPROTO;
+                       *gbuf_rptr(mioc) = (u_char)EPROTOTYPE;
                        gbuf_wset(mioc, 1);
                        if (gbuf_cont(mioc)) {
                                gbuf_freem(gbuf_cont(mioc));
@@ -1912,8 +1914,8 @@ asp_putnext(gref, mproto)
 
 int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, int flags, int *errp)
 {
-    int s, i, err, len;
-    gbuf_t *mioc, *mdata, *mx;
+    int s, i, err, len, offset, remain, size, copy_len;
+    gbuf_t *mioc, *mdata, *mx, *m0;
     ioc_t *iocbp;
     strbuf_t ctlbuf;
     strbuf_t datbuf;
@@ -1927,6 +1929,7 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in
     asp_word_t *awp;
     union asp_primitives *primitives;
     unsigned short tid;
+    caddr_t            dataptr;
     
     if ((scb = (asp_scb_t *)gref->info) == 0) {
                dPrintf(D_M_ASP, D_L_ERROR,
@@ -1953,9 +1956,9 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in
         bcopy (datptr, &datbuf, sizeof (strbuf_t));
      } else {
         /* being called from user space */
-        if ((err = copyin((caddr_t)ctlptr, (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
+        if ((err = copyin(CAST_USER_ADDR_T(ctlptr), (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
             goto l_err;
-        if ((err = copyin((caddr_t)datptr, (caddr_t)&datbuf, sizeof(datbuf))) != 0)
+        if ((err = copyin(CAST_USER_ADDR_T(datptr), (caddr_t)&datbuf, sizeof(datbuf))) != 0)
             goto l_err;
      }
 
@@ -1975,7 +1978,7 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in
         bcopy (ctlbuf.buf, gbuf_rptr(mioc), ctlbuf.len);
     } else {
         /* being called from user space */
-        if ((err = copyin((caddr_t)ctlbuf.buf, (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
+        if ((err = copyin(CAST_USER_ADDR_T(ctlbuf.buf), (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
             gbuf_freem(mioc);
             goto l_err;
         }
@@ -1988,46 +1991,77 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in
                ("ASPputmsg: %s\n", aspCmdStr(Primitive)));
 
     /*
-     * allocate buffer and copy in the data content
+     * copy in the data content into multiple mbuf clusters if
+     * required.  ATP now expects reply data to be placed in
+     * standard clusters, not the large external clusters that
+     * were used previously.
      */
-    len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize;
+         
+    /* set offset for use by some commands */
+    offset = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize;
+       size = 0;
+    if (mreq != NULL) {
+        /* The data from the in-kernel call for use by AFP is passed
+         * in as one large external cluster.  This needs to be copied
+         * to a chain of standard clusters.
+         */
+        remain = gbuf_len(mreq);
+        dataptr = mtod(mreq, caddr_t);
+    } else {
+       /* copyin from user space */
+       remain = datbuf.len; 
+       dataptr = (caddr_t)datbuf.buf;  
+    }  
     
-    if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) {
+    /* allocate first buffer */
+    if (!(mdata = gbuf_alloc_wait((remain + offset > MCLBYTES ? MCLBYTES : remain + offset), TRUE))) {
         /* error return should not be possible */
         err = ENOBUFS;
         gbuf_freem(mioc);
         goto l_err;
     }
-    gbuf_wset(mdata, (datbuf.len+len));
+    gbuf_wset(mdata, 0);               /* init length to zero */
     gbuf_cont(mioc) = mdata;
-    
-    if (mreq != NULL) {
-        /* being called from kernel space */
-        gbuf_t *tmp = mreq;
-        unsigned long offset = 0;
-        
-        /* copy afp cmd data from the passed in mbufs to mdata.  I cant
-        chain mreq to mdata since the rest of this code assumes
-        just one big mbuf with space in front for the BDS */
-        offset = len;
-        while (tmp != NULL) {
-            bcopy (gbuf_rptr(tmp), (gbuf_rptr(mdata) + offset), gbuf_len(tmp));
-            offset += gbuf_len(tmp);
-            tmp = gbuf_cont(tmp);           /* on to next mbuf in chain */
-        }
-        
-        /* all data copied out of mreq so free it */
-        gbuf_freem(mreq);
-    } else {
-        /* being called from user space */
-        if ((err = copyin((caddr_t)datbuf.buf,
-                  (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) {
-            gbuf_freem(mioc);
-            goto l_err;
-        }
-    }
 
-    switch (Primitive) {
+       while (remain) {
+               if (remain + offset > MCLBYTES)
+                       copy_len = MCLBYTES - offset;
+               else
+                       copy_len = remain;
+               remain -= copy_len;
+               if (mreq != NULL)
+                       bcopy (dataptr, (gbuf_rptr(mdata) + offset), copy_len);
+               else if ((err = copyin(CAST_USER_ADDR_T(dataptr), (caddr_t)(gbuf_rptr(mdata) + offset), copy_len)) != 0) {
+                       gbuf_freem(mioc);
+                       goto l_err;
+               }
+               gbuf_wset(mdata, (copy_len + offset));
+               size += copy_len + offset;
+               dataptr += copy_len;
+               offset = 0;
+               if (remain) {
+                       /* allocate the next mbuf */
+                       if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) {
+                               err = ENOBUFS;
+                               gbuf_freem(mioc);
+                               goto l_err;
+                       }
+                       mdata = gbuf_cont(mdata);
+                       MCLGET(mdata, M_WAIT);
+                       if (!(mdata->m_flags & M_EXT)) {
+                               err = ENOBUFS;
+                               gbuf_freem(mioc);
+                               goto l_err;
+                       }
+               }
+       }
+       mdata = gbuf_cont(mioc);                        /* code further on down expects this to b e set */
+       mdata->m_pkthdr.len = size;                     /* set packet hdr len */
+
+       if (mreq != 0)
+               gbuf_freem(mreq);
+
+       switch (Primitive) {
 
     case ASPFUNC_Command:
     case ASPFUNC_Write:
@@ -2144,16 +2178,20 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in
             atp->xo = 1;
             atp->xo_relt = 1;
         }
+        /* setup the atpBDS struct - only the length field is used,
+         * except for the first one which contains the bds count in
+         * bdsDataSz.
+         */
         atpBDS = (struct atpBDS *)gbuf_wptr(mioc);
         msize = mdata ? gbuf_msgsize(mdata) : 0;
-       for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
+               for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) {
             len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE;
             msize -= ATP_DATA_SIZE;
             *(long *)atpBDS[nbds].bdsUserData = 0;
             UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1);
             UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len);
         }
-        UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
+               UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
         *(long *)atpBDS[0].bdsUserData = (long)result;
         *(long *)atp->user_bytes = (long)result;
         gbuf_winc(mioc,atpBDSsize);
@@ -2205,7 +2243,8 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply,
      */
     while ((mproto = scb->sess_ioc) == 0) {
         scb->get_wait = 1;
-        err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0);
+          lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED);
+        err = msleep(&scb->event, atalk_mutex, PSOCK | PCATCH, "aspgetmsg", 0);
         if (err != 0) {
             scb->get_wait = 0;
             ATENABLE(s, scb->lock);
@@ -2243,10 +2282,10 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply,
         bcopy (datptr, &datbuf, sizeof(datbuf));
     } else {
         /* called from user space */
-        if ((err = copyin((caddr_t)ctlptr,
+        if ((err = copyin(CAST_USER_ADDR_T(ctlptr),
                 (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
             goto l_err;
-        if ((err = copyin((caddr_t)datptr,
+        if ((err = copyin(CAST_USER_ADDR_T(datptr),
                 (caddr_t)&datbuf, sizeof(datbuf))) != 0)
             goto l_err;
     }
@@ -2285,10 +2324,10 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply,
     } else {
         /* called from user space */
         if ((err = copyout((caddr_t)gbuf_rptr(mproto),
-                (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0)
+                CAST_USER_ADDR_T(ctlbuf.buf), ctlbuf.len)) != 0)
             goto l_err;
         if ((err = copyout((caddr_t)&ctlbuf,
-                (caddr_t)ctlptr, sizeof(ctlbuf))) != 0)
+                CAST_USER_ADDR_T(ctlptr), sizeof(ctlbuf))) != 0)
             goto l_err;
     }
 
@@ -2306,7 +2345,7 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply,
             
             if (mreply == NULL) {
                 /* called from user space */
-                if ((err = copyout((caddr_t)gbuf_rptr(mdata), (caddr_t)&datbuf.buf[sum], len)) != 0)
+                if ((err = copyout((caddr_t)gbuf_rptr(mdata), CAST_USER_ADDR_T(&datbuf.buf[sum]), len)) != 0)
                     goto l_err;
             }
             sum += len;
@@ -2318,7 +2357,7 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply,
         bcopy (&datbuf, datptr, sizeof(datbuf));
     } else {
         /* called from user space */
-        if ((err = copyout((caddr_t)&datbuf, (caddr_t)datptr, sizeof(datbuf))) != 0)
+        if ((err = copyout((caddr_t)&datbuf, CAST_USER_ADDR_T(datptr), sizeof(datbuf))) != 0)
             goto l_err;
     }