]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/asp_proto.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / bsd / netat / asp_proto.c
index a9302545438273f3e348a61acd4a010ffeaeaa87..8f1621b54fbf51c7cc7afbc17247b14a215ca84a 100644 (file)
@@ -1,27 +1,31 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1995-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_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. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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,
  * 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@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
- *     Copyright (c) 1995 Apple Computer, Inc. 
- *
  *  Change Log:
  *    Created February 20, 1995 by Tuyen Nguyen
  *    Modified for MP, 1996 by Tuyen Nguyen
 #include <sys/mbuf.h>
 #include <sys/ioctl.h>
 #include <sys/malloc.h>
+#include <kern/locks.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 
 #include <net/if.h>
 
-#include <netat/appletalk.h>
 #include <netat/sysglue.h>
+#include <netat/appletalk.h>
 #include <netat/at_pcb.h>
 #include <netat/atp.h>
 #include <netat/ddp.h>
 #include <netat/at_var.h>
 #include <netat/debug.h>
 
-static int loop_cnt;
-#define CHK_LOOP(str) { \
-  if (loop_cnt++ > 100) { \
-     kprintf("%s", str); \
-     break; \
-  } \
-}
 
 #define atpBDSsize    (sizeof(struct atpBDS)*ATP_TRESP_MAX)
 #define aspCMDsize    (atpBDSsize+sizeof(struct atp_set_default)+TOTAL_ATP_HDR_SIZE)
@@ -75,36 +73,27 @@ static int loop_cnt;
        && ((scb->rem_addr.net != addr.net) \
                || (scb->rem_addr.node != addr.node)) )
 
-int  ASPputmsg();
-int  ASPgetmsg();
-void asp_init();
-void asp_ack_reply();
-void asp_nak_reply();
-void asp_clock();
-void asp_clock_funnel();
-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();
-
-StaticProc void asp_putnext();
-StaticProc void asp_iocack();
-StaticProc void asp_iocnak();
-StaticProc void asp_dequeue_scb();
-StaticProc void asp_scb_free();
-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_accept();
-StaticProc int  asp_send_req();
+StaticProc asp_scb_t *asp_find_scb(unsigned char, at_inet_t *);
+StaticProc asp_scb_t *asp_scb_alloc(void);
+
+StaticProc void asp_putnext(gref_t *, gbuf_t *);
+StaticProc void asp_iocack(gref_t *, gbuf_t *);
+StaticProc void asp_iocnak(gref_t *, gbuf_t *, int);
+StaticProc void asp_dequeue_scb(asp_scb_t *);
+StaticProc void asp_scb_free(asp_scb_t *);
+StaticProc void asp_timout(asp_tmo_func,  asp_scb_t *, int);
+StaticProc void asp_untimout(asp_tmo_func,  asp_scb_t *);
+StaticProc void asp_hangup(asp_scb_t *);
+StaticProc void asp_send_tickle(asp_scb_t *);
+StaticProc void asp_send_tickle_locked(void *);
+StaticProc void asp_accept(asp_scb_t *scb, asp_scb_t *sess_scb, gbuf_t *m);
+StaticProc int  asp_send_req(gref_t *, gbuf_t *, at_inet_t *, at_retry_t *, asp_word_t *, 
+                                                       unsigned char , unsigned char, unsigned char);
 
 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];
@@ -114,7 +103,8 @@ static unsigned char scb_tmo_cnt;
 asp_scb_t *scb_used_list;
 static asp_scb_t *scb_tmo_list;
 asp_scb_t *scb_free_list;
-atlock_t aspall_lock, asptmo_lock;
+
+int asp_readable(gref_t *);
 
 int
 asp_readable(gref)
@@ -140,7 +130,6 @@ asp_init()
 int asp_open(gref)
        gref_t *gref;
 {
-       int s;
        asp_scb_t *scb;
 
        /*
@@ -165,11 +154,9 @@ int asp_open(gref)
        scb->gref = gref;
        scb->session_timer = DEF_SESS_TMO;
        scb->cmd_retry = asp_def_retry;
-       ATDISABLE(s, aspall_lock);
        if ((scb->next_scb = scb_used_list) != 0)
                scb->next_scb->prev_scb = scb;
        scb_used_list = scb;
-       ATENABLE(s, aspall_lock);
 
        /*
         * return success
@@ -185,7 +172,6 @@ int
 asp_close(gref)
        gref_t *gref;
 {
-       int s;
        unsigned char sock_num;
        asp_scb_t *scb, *new_scb;
        gbuf_t *m;
@@ -199,17 +185,14 @@ asp_close(gref)
                 * send the CloseSess response to peer
                 */
                if (gbuf_type(scb->sess_ioc) != MSG_PROTO) {
-                       ATDISABLE(s, scb->lock);
                        m = scb->sess_ioc;
                        scb->sess_ioc = gbuf_next(m);
-                       ATENABLE(s, scb->lock);
                        atp_send_rsp(scb->gref, m, TRUE);
                }
        }
 
        if (scb->atp_state) {
                sock_num = scb->loc_addr.socket;
-               ATDISABLE(s, aspall_lock);
                if ((scb->dflag != 1) && scb->stat_msg) {
                        untimeout(atp_retry_req, scb->stat_msg);
                        gbuf_freem(scb->stat_msg);
@@ -218,7 +201,6 @@ asp_close(gref)
                if (asp_scbQ[sock_num]->next_scb == 0) {
                        asp_scbQ[sock_num] = 0;
                        asp_inpC[sock_num] = 0;
-                       ATENABLE(s, aspall_lock);
                        dPrintf(D_M_ASP, D_L_INFO,
                        ("         : atp_close(), loc=%d\n", scb->loc_addr.socket));
                        atp_close(gref, 0);
@@ -236,7 +218,6 @@ asp_close(gref)
                                        scb->next_scb->prev_scb = scb->prev_scb;
                        }
                        scb->next_scb = 0;
-                       ATENABLE(s, aspall_lock);
                }
        } else
                asp_dequeue_scb(scb);
@@ -244,7 +225,6 @@ asp_close(gref)
        /*
         * free all allocated blocks if any
         */
-       ATDISABLE(s, scb->lock);
        if (scb->stat_msg) {
                gbuf_freem(scb->stat_msg);
                scb->stat_msg = 0;
@@ -259,14 +239,13 @@ asp_close(gref)
        }
 
        scb->rem_addr.node = 0;
-       ATENABLE(s, scb->lock);
 
        /*
         * stop all timers
         */
        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
@@ -276,7 +255,11 @@ asp_close(gref)
        return 0;
 } /* asp_close */
 
-static char *aspStateStr(state)
+#if DEBUG
+
+static const char *aspStateStr(int);
+
+static const char *aspStateStr(state)
      int state;
 {
   return ((state==ASPSTATE_Close)? "Close":
@@ -291,7 +274,9 @@ static char *aspStateStr(state)
          "unknown");
 }
 
-static char *aspCmdStr(aspCmd)
+static const char *aspCmdStr(int);
+
+static const char *aspCmdStr(aspCmd)
      int aspCmd;
 { 
 return ((aspCmd==ASPFUNC_CloseSess)? "CloseSess":
@@ -305,7 +290,9 @@ return ((aspCmd==ASPFUNC_CloseSess)? "CloseSess":
        (aspCmd==ASPFUNC_CmdReply)? "CmdReply": "unknown");
 }
 
-static char *aspIOCStr(aspIOC)
+static const char *aspIOCStr(int);
+
+static const char *aspIOCStr(aspIOC)
      int aspIOC;
 {
 return (
@@ -325,13 +312,14 @@ return (
        "unknown"
        );
 }
+#endif /* DEBUG */
 
 #ifdef AT_MBUF_TRACE
 
 static char mbuf_str[100];
 char *mbuf_totals() 
 {
-  sprintf(mbuf_str, 
+  snprintf(mbuf_str, sizeof(mbuf_str),
          /*
          "dat = %d, prot = %d, ioc = %d, err = %d, hu = %d, ack = %d, nak = %d, ctl = %d",
          */
@@ -371,7 +359,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
@@ -380,7 +368,7 @@ int asp_wput(gref, m)
        gref_t *gref;
        gbuf_t *m;
 {
-       int s, err;
+       int err;
        unsigned char sockSav, sock_num;
        gbuf_t *mioc, *mdata;
        ioc_t *iocbp;
@@ -494,7 +482,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 +490,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 +498,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 +507,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;
                }
 
@@ -545,7 +533,6 @@ int asp_wput(gref, m)
                if ((sock_num = (at_socket)atp_bind(gref, 0, &sockSav)) == 0) {
                        atp_close(gref, 0);
                        asp_dequeue_scb(scb);
-                       ATDISABLE(s, aspall_lock);
                        sock_num = sockSav;
                        scb->loc_addr.socket = sock_num;
                        for (curr_scb = asp_scbQ[sock_num];
@@ -553,14 +540,11 @@ int asp_wput(gref, m)
                        scb->prev_scb = curr_scb;
                        curr_scb->next_scb = scb;
                        scb->atp_state = curr_scb->atp_state;
-                       ATENABLE(s, aspall_lock);
                } else {
                        asp_dequeue_scb(scb);
-                       ATDISABLE(s, aspall_lock);
                        scb->loc_addr.socket = sock_num;
                        asp_scbQ[sock_num] = scb;
                        scb->atp_state->dflag = scb->dflag;
-                       ATENABLE(s, aspall_lock);
                }
                gref->info = (void *)scb;
                asp_inpC[sock_num]++;
@@ -580,8 +564,9 @@ int asp_wput(gref, m)
                aw.param2 = 0;
                scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
                iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
+               /* bms:  make sure this is an ALO request */
                asp_send_req(gref, mioc, &status_cmd->SLSEntityIdentifier,
-                            &status_cmd->Retry, &aw, 1, ASPSTATE_WaitingForGetStatusRsp, 0xff);
+                            &status_cmd->Retry, &aw, 0, ASPSTATE_WaitingForGetStatusRsp, 0xff);
                gbuf_freeb(mdata);
                return 0;
 
@@ -600,7 +585,7 @@ int asp_wput(gref, m)
                scb->session_timer = open_cmd->SessionTimer;
                aw.func = ASPFUNC_OpenSess;
                aw.param1 = scb->loc_addr.socket;
-               aw.param2 = ASP_Version;
+               aw.param2 = htons(ASP_Version);
                scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff);
                iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
                asp_send_req(gref, mioc, &open_cmd->SLSEntityIdentifier,
@@ -658,7 +643,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);
@@ -774,15 +759,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();
 }
 
 
@@ -810,7 +795,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));
@@ -832,7 +817,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;
        }
 }
@@ -846,7 +831,6 @@ asp_accept(scb, sess_scb, m)
        asp_scb_t *sess_scb;
        gbuf_t *m;
 {
-       int s;
        gbuf_t *mdata;
        at_ddp_t *ddp;
        at_atp_t *atp;
@@ -878,9 +862,7 @@ asp_accept(scb, sess_scb, m)
        awp->param1 = sess_scb->sess_id;
        awp->param2 = 0;
        gbuf_freeb(m);
-       ATDISABLE(s, scb->lock);
        scb->sess_ioc = gbuf_next(mdata);
-       ATENABLE(s, scb->lock);
        gbuf_next(mdata) = 0;
        asp_timout(asp_hangup, sess_scb, sess_scb->session_timer);
        atp_send_rsp(scb->gref, mdata, TRUE);
@@ -893,14 +875,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();
 }
 
 /*
@@ -909,11 +891,9 @@ void asp_clock_funnel(arg)
 void asp_clock(arg)
        void *arg;
 {
-       int s;
        asp_scb_t *scb;
-       void (*tmo_func)();
-
-       ATDISABLE(s, asptmo_lock);
+       asp_tmo_func tmo_func;
+       
        if (scb_tmo_list)
                scb_tmo_list->tmo_delta--;
        while (((scb = scb_tmo_list) != 0) && (scb_tmo_list->tmo_delta == 0)) {
@@ -921,15 +901,12 @@ void asp_clock(arg)
                        scb_tmo_list->prev_tmo = 0;
                if ((tmo_func = scb->tmo_func) != 0) {
                        scb->tmo_func = 0;
-                       ATENABLE(s, asptmo_lock);
                        (*tmo_func)(scb);
-                       ATDISABLE(s, asptmo_lock);
                }
        }
-       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);
         
 }
 
@@ -941,7 +918,6 @@ asp_ack_reply(gref, mioc)
        register gref_t *gref;
        register gbuf_t *mioc;
 {
-       int s;
        int len, msize, nbds;
        register gbuf_t *mdata, *m, *mx;
        struct atpBDS *atpBDS;
@@ -1081,7 +1057,7 @@ asp_ack_reply(gref, mioc)
                                 */
                                awp->func = 0;
                                awp->param1 = 0;
-                               awp->param2 = (unsigned short)ASPERR_BadVersNum;
+                               awp->param2 = htons((unsigned short)ASPERR_BadVersNum);
                                dPrintf(D_M_ASP, D_L_INFO,
                                        ("             : version=%d\n",
                                        ASPERR_BadVersNum));
@@ -1098,12 +1074,11 @@ asp_ack_reply(gref, mioc)
                        /*
                         * queue the connection request
                         */
-                       ATDISABLE(s, scb->lock);
                        gbuf_next(mdata) = 0;
                        if ((m = scb->sess_ioc) == 0) {
                                scb->sess_ioc = mdata;
                                if (scb->get_wait)
-                                       thread_wakeup(&scb->event);
+                                       wakeup(&scb->event);
                                else
                                        atalk_notify_sel(gref);
                        } else {
@@ -1111,7 +1086,6 @@ asp_ack_reply(gref, mioc)
                                        m = gbuf_next(m);
                                gbuf_next(m) = mdata;
                        }
-                       ATENABLE(s, scb->lock);
                        dPrintf(D_M_ASP, D_L_INFO,
                                ("             : QUEUE connect request\n"));
 
@@ -1120,11 +1094,11 @@ asp_ack_reply(gref, mioc)
                case ASPFUNC_Command:
                case ASPFUNC_Write:
                        if ( (scb->sess_id != awp->param1)
-                            || (scb->rcv_seq_num != awp->param2)
+                            || (scb->rcv_seq_num != ntohs(awp->param2))
                             || BAD_REMADDR(rem_addr) ) {
                                char era[8], ra[8];
-                               sprintf(era,"%d.%d", scb->rem_addr.node,scb->rem_addr.socket);
-                               sprintf(ra,"%d.%d", rem_addr.node,rem_addr.socket);
+                               snprintf(era, sizeof(era), "%d.%d", scb->rem_addr.node,scb->rem_addr.socket);
+                               snprintf(ra, sizeof(ra), "%d.%d", rem_addr.node,rem_addr.socket);
                                dPrintf(D_M_ASP, D_L_WARNING,
                                        ("             : DROP, id=%d,esn=%d,sn=%d,erem=%s,rem=%s\n",
                                        scb->sess_id,scb->rcv_seq_num,awp->param2,era,ra));
@@ -1142,12 +1116,11 @@ asp_ack_reply(gref, mioc)
                        command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
                        command_ind->Primitive = (int)awp->func;
                        command_ind->ReqRefNum =
-                               *(unsigned short *)atp->tid;
+                               ntohs(*(unsigned short *)atp->tid);
                        command_ind->ReqType = awp->func;
 
                        mdata = gbuf_strip(mdata);
                        gbuf_cont(mioc) = mdata;
-                       ATDISABLE(s, scb->lock);
                        if (scb->req_flag) {
                                if ((mx = scb->req_msgq) != 0) {
                                        while (gbuf_next(mx))
@@ -1155,10 +1128,8 @@ asp_ack_reply(gref, mioc)
                                        gbuf_next(mx) = mioc;
                                } else
                                        scb->req_msgq = mioc;
-                               ATENABLE(s, scb->lock);
                        } else {
                                scb->req_flag = 1;
-                               ATENABLE(s, scb->lock);
                                asp_putnext(scb->gref, mioc);
                        }
                        goto l_done;
@@ -1175,7 +1146,7 @@ asp_ack_reply(gref, mioc)
                        command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
                        command_ind->Primitive = (int)awp->func;
                        command_ind->ReqRefNum =
-                               *(unsigned short *)atp->tid;
+                               ntohs(*(unsigned short *)atp->tid);
                        command_ind->ReqType = awp->func;
 
                        mdata = gbuf_strip(mdata);
@@ -1244,12 +1215,10 @@ asp_ack_reply(gref, mioc)
                                scb->rem_addr.socket));
 
                        gbuf_next(mdata) = 0;
-                       ATDISABLE(s, scb->lock);
                        if (scb->sess_ioc)
                                gbuf_freel(scb->sess_ioc);
                        scb->sess_ioc = mdata;
                        scb->state = ASPSTATE_Close;
-                       ATENABLE(s, scb->lock);
 
                        /*
                         * notify upstream of the CloseSess from peer
@@ -1268,7 +1237,7 @@ asp_ack_reply(gref, mioc)
                        command_ind = (asp_command_ind_t *)gbuf_rptr(mioc);
                        command_ind->Primitive = (int)awp->func;
                        command_ind->ReqRefNum =
-                               *(unsigned short *)atp->tid;
+                               ntohs(*(unsigned short *)atp->tid);
                        command_ind->ReqType = awp->func;
                        scb->attn_tid = *(unsigned short *)atp->tid;
                        scb->attn_flag = 1;
@@ -1314,12 +1283,10 @@ asp_ack_reply(gref, mioc)
                case ASPSTATE_Idle:
                        scb->rem_addr.node = 0;
                        gbuf_freem(mioc);
-                       ATDISABLE(s, scb->lock);
                        if (scb->get_wait)
-                               thread_wakeup(&scb->event);
+                               wakeup(&scb->event);
                        else
                                atalk_notify_sel(gref);
-                       ATENABLE(s, scb->lock);
                        return;
 
                case ASPSTATE_WaitingForGetStatusRsp:
@@ -1357,6 +1324,9 @@ asp_ack_reply(gref, mioc)
                        } else {
                                scb->rem_addr.node = scb->rem_node;
                                scb->rem_addr.socket = awp->func;
+                               /* bms:  need to set the reply_socket for client side too.
+                               This makes ALO atten replies sent by the client work. */
+                               scb->reply_socket = scb->rem_addr.socket;
                                scb->sess_id = awp->param1;
                                gbuf_freeb(mx);
                                atalk_putnext(gref, mioc);
@@ -1385,7 +1355,7 @@ asp_ack_reply(gref, mioc)
                        atpBDS = (struct atpBDS *)gbuf_rptr(mx);
                        cmdreply_ind = (asp_cmdreply_ind_t *)gbuf_rptr(mioc);
                        cmdreply_ind->Primitive = ASPFUNC_CmdReply;
-                       cmdreply_ind->CmdResult = *(int *)atpBDS->bdsUserData;
+                       cmdreply_ind->CmdResult = ntohl(*(int *)atpBDS->bdsUserData);
                        gbuf_wset(mioc,sizeof(asp_cmdreply_ind_t));
                        gbuf_freeb(mx);
                        asp_putnext(scb->gref, mioc);
@@ -1517,7 +1487,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));
@@ -1581,9 +1551,7 @@ StaticProc void
 asp_dequeue_scb(scb)
        asp_scb_t *scb;
 {
-       int s;
 
-       ATDISABLE(s, aspall_lock);
        if (scb == scb_used_list) {
                if ((scb_used_list = scb->next_scb) != 0)
                        scb->next_scb->prev_scb = 0;
@@ -1591,7 +1559,6 @@ asp_dequeue_scb(scb)
                if ((scb->prev_scb->next_scb = scb->next_scb) != 0)
                        scb->next_scb->prev_scb = scb->prev_scb;
        }
-       ATENABLE(s, aspall_lock);
 
        scb->next_scb = 0;
        scb->prev_scb = 0;
@@ -1605,11 +1572,9 @@ asp_find_scb(sock_num, rem_addr)
        unsigned char sock_num;
        at_inet_t *rem_addr;
 {
-       int s;
        asp_scb_t *scb;
        asp_scb_t *alt_scb = 0;
 
-       ATDISABLE(s, aspall_lock);
        for (scb = asp_scbQ[sock_num]; scb; scb = scb->next_scb) {
                if ((scb->rem_addr.net == rem_addr->net)
                        && (scb->rem_addr.node == rem_addr->node)) {
@@ -1629,7 +1594,6 @@ asp_find_scb(sock_num, rem_addr)
                        rem_addr->node,
                        rem_addr->socket));
        }
-       ATENABLE(s, aspall_lock);
 
        return scb;
 }
@@ -1639,11 +1603,10 @@ asp_find_scb(sock_num, rem_addr)
  */
 StaticProc void
 asp_timout(func, scb, seconds)
-       void (*func)();
+       asp_tmo_func func;
        register asp_scb_t *scb;
        int seconds;
 {
-       int s;
        unsigned char sum;
        register asp_scb_t *curr_scb, *prev_scb;
 
@@ -1654,11 +1617,9 @@ asp_timout(func, scb, seconds)
        scb->tmo_delta = (seconds>>SESS_TMO_RES);
        scb->tmo_cnt = scb_tmo_cnt;
 
-       ATDISABLE(s, asptmo_lock);
        if (scb_tmo_list == 0) {
                scb->next_tmo = scb->prev_tmo = 0;
                scb_tmo_list = scb;
-               ATENABLE(s, asptmo_lock);
                return;
        }
 
@@ -1692,23 +1653,20 @@ asp_timout(func, scb, seconds)
                scb_tmo_list->prev_tmo = scb;
                scb_tmo_list = scb;
        }
-       ATENABLE(s, asptmo_lock);
 }
 
 /*
  * untimout routine
  */
 StaticProc void
-asp_untimout(func, scb)
-       void (*func)();
-       register asp_scb_t *scb;
+asp_untimout(
+       __unused asp_tmo_func tmo_func,
+       register asp_scb_t *scb)
 {
-       int s;
 
        if ((scb->tmo_cnt == scb_tmo_cnt) || (scb->tmo_func == 0))
                return;
 
-       ATDISABLE(s, asptmo_lock);
        if (scb_tmo_list == scb) {
                if ((scb_tmo_list = scb->next_tmo) != 0) {
                        scb_tmo_list->prev_tmo = 0;
@@ -1722,7 +1680,6 @@ asp_untimout(func, scb)
                scb->prev_tmo = 0;
        }
        scb->tmo_func = 0;
-       ATENABLE(s, asptmo_lock);
 }
 
 /*
@@ -1732,12 +1689,9 @@ StaticProc void
 asp_hangup(scb)
        asp_scb_t *scb;
 {
-       int s;
-
        /*
         * set the state to Close
         */
-       ATDISABLE(s, scb->lock);
        scb->state = ASPSTATE_Close;
        if (scb->tickle_tid) {
                atp_cancel_req(scb->gref, (unsigned int)scb->tickle_tid);
@@ -1748,15 +1702,11 @@ asp_hangup(scb)
         * notify upstream of the hangup
         */
        if (scb->rem_addr.node) {
-               if (scb->get_wait) {
-                       thread_wakeup(&scb->event);
-                       ATENABLE(s, scb->lock);
-               } else {
-                       ATENABLE(s, scb->lock);
+               if (scb->get_wait)
+                       wakeup(&scb->event);
+               else
                        atalk_notify_sel(scb->gref);
-               }
-       } else
-               ATENABLE(s, scb->lock);
+       }
 }
 
 StaticProc void
@@ -1799,17 +1749,13 @@ asp_iocnak(gref, mioc, err)
 StaticProc asp_scb_t *
 asp_scb_alloc()
 {
-       int s, i;
+       int i;
        gbuf_t *m;
        asp_scb_t *scb, *scb_array;
 
-       ATDISABLE(s, aspall_lock);
        if (scb_free_list == 0) {
                if ((m = gbuf_alloc(SCBS_PER_BLK*sizeof(asp_scb_t), PRI_MED)) == 0)
-               {
-                       ATENABLE(s, aspall_lock);
                        return (asp_scb_t *)0;
-               }
                bzero((char *)gbuf_rptr(m), SCBS_PER_BLK*sizeof(asp_scb_t));
                gbuf_cont(m) = scb_resource_m;
                scb_resource_m = m;
@@ -1822,9 +1768,6 @@ asp_scb_alloc()
 
        scb = scb_free_list;
        scb_free_list = scb->next_scb;
-       ATENABLE(s, aspall_lock);
-       ATLOCKINIT(scb->lock);
-       ATLOCKINIT(scb->delay_lock);
        ATEVENTINIT(scb->event);
        ATEVENTINIT(scb->delay_event);
 
@@ -1838,13 +1781,10 @@ StaticProc void
 asp_scb_free(scb)
        asp_scb_t *scb;
 {
-       int s;
 
        bzero((char *)scb, sizeof(asp_scb_t));
-       ATDISABLE(s, aspall_lock);
        scb->next_scb = scb_free_list;
        scb_free_list = scb;
-       ATENABLE(s, aspall_lock);
 }
 
 /*
@@ -1855,7 +1795,6 @@ asp_putnext(gref, mproto)
        gref_t *gref;
        gbuf_t *mproto;
 {
-       int s;
        gbuf_t *m;
        asp_scb_t *scb;
 
@@ -1864,7 +1803,6 @@ asp_putnext(gref, mproto)
        /*
         * queue the message.
         */
-       ATDISABLE(s, scb->lock);
        gbuf_next(mproto) = 0;
        if ((m = scb->sess_ioc) == 0)
                scb->sess_ioc = mproto;
@@ -1877,14 +1815,11 @@ asp_putnext(gref, mproto)
        if (scb->rcv_cnt >= MAX_RCV_CNT)
                scb->snd_stop = 1;
 
-       if (scb->get_wait) {
-               thread_wakeup(&scb->event);
-               ATENABLE(s, scb->lock);
-       } else if (mproto == scb->sess_ioc) {
-               ATENABLE(s, scb->lock);
+       if (scb->get_wait)
+               wakeup(&scb->event);
+       else if (mproto == scb->sess_ioc)
                atalk_notify_sel(gref);
-       } else
-               ATENABLE(s, scb->lock);
+
 } /* asp_putnext */
 
 /*
@@ -1894,265 +1829,338 @@ asp_putnext(gref, mproto)
 
 /* in ASPputmsg we expect:
 
-       ASPFUNC_CmdReply
-       ASPFUNC_Attention
-       ASPFUNC_Command
-       ASPFUNC_Write
-       ASPFUNC_WriteContinue
+    ASPFUNC_CmdReply
+    ASPFUNC_Attention
+    ASPFUNC_Command
+    ASPFUNC_Write
+    ASPFUNC_WriteContinue
+    
+    bms:  Make this callable from the kernel.
+    If mreq != NULL, then must be called from kernel space and the following apply:
+    1)  *mreq is data to be sent already in mbuf chains.
+    2)  datptr->len = size of data
 */
 
-int ASPputmsg(gref, ctlptr, datptr, flags, errp)
-       gref_t *gref;
-       strbuf_t *ctlptr;
-       strbuf_t *datptr;
-       int flags;
-       int *errp;
+int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, __unused int flags, int *errp)
 {
-       int s, i, err, len;
-       gbuf_t *mioc, *mdata, *mx;
-       ioc_t *iocbp;
-       strbuf_t ctlbuf;
-       strbuf_t datbuf;
-       asp_scb_t *scb;
-       int nbds, result, msize, Primitive;
-       unsigned char *wptr;
-       struct atp_set_default *sd;
-       at_ddp_t *ddp;
-       at_atp_t *atp;
-       struct atpBDS *atpBDS;
-       asp_word_t *awp;
-       union asp_primitives *primitives;
-       unsigned short tid;
-
-       if ((scb = (asp_scb_t *)gref->info) == 0) {
+    int i, err, len, offset, remain, size, copy_len;
+    gbuf_t *mioc, *mdata, *mx;
+    ioc_t *iocbp;
+    strbuf_t ctlbuf;
+    strbuf_t datbuf;
+    asp_scb_t *scb;
+    int nbds, result, msize, Primitive;
+    unsigned char *wptr;
+    struct atp_set_default *sd;
+    at_ddp_t *ddp;
+    at_atp_t *atp;
+    struct atpBDS *atpBDS;
+    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,
                        ("ASPputmsg: stale handle=0x%x, pid=%d\n",
                        (u_int) gref, gref->pid));
 
-               *errp = EINVAL;
-               return -1;
-       }
-
-       if (scb->state == ASPSTATE_Close)
-               return 0;
-       if (scb->snd_stop) {
-               *errp = EAGAIN;
-               return -1;
-       }
-
-       /*
-        * copy in the control and data info
-        */
-       if ((err = copyin((caddr_t)ctlptr,
-                       (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
-               goto l_err;
-       if ((err = copyin((caddr_t)datptr,
-                       (caddr_t)&datbuf, sizeof(datbuf))) != 0)
-               goto l_err;
-
-       /*
-        * allocate buffer and copy in the control content
-        */
-       if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) {
-               /* error return should not be possible */
-               err = ENOBUFS;
-               goto l_err;
-       }
-       gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */
-       gbuf_wset(mioc, ctlbuf.len);
-       if ((err = copyin((caddr_t)ctlbuf.buf,
-                       (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
-               gbuf_freem(mioc);
-               goto l_err;
-       }
+        *errp = EINVAL;
+        return -1;
+    }
+
+    if (scb->state == ASPSTATE_Close)
+        return 0;
+    if (scb->snd_stop) {
+        *errp = EAGAIN;
+        return -1;
+    }
+
+    /*
+     * copy in the control and data info
+     */
+     if (mreq != NULL) {
+        /* being called from kernel space */
+        bcopy (ctlptr, &ctlbuf, sizeof (strbuf_t));
+        bcopy (datptr, &datbuf, sizeof (strbuf_t));
+     } else {
+        /* being called from user space */
+        if ((err = copyin(CAST_USER_ADDR_T(ctlptr), (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
+            goto l_err;
+        if ((err = copyin(CAST_USER_ADDR_T(datptr), (caddr_t)&datbuf, sizeof(datbuf))) != 0)
+            goto l_err;
+     }
+
+     /* Radar 5398072: check for bogus length
+      *               Max ASP data is 8 ATP packets
+      */
+
+     if ((ctlbuf.len < 0) || (ctlbuf.len > (ATP_DATA_SIZE * 8))) {
+            err = EINVAL;
+            goto l_err;
+     }
+     if ((datbuf.len < 0) || (datbuf.len > (ATP_DATA_SIZE * 8))) {
+            err = EINVAL;
+            goto l_err;
+     }
+
+    /*
+     * allocate buffer and copy in the control content
+     */
+    if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) {
+        /* error return should not be possible */
+        err = ENOBUFS;
+        goto l_err;
+    }
+    gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */
+    gbuf_wset(mioc, ctlbuf.len);
+    
+    if (mreq != NULL) {
+        /* being called from kernel space */
+        bcopy (ctlbuf.buf, gbuf_rptr(mioc), ctlbuf.len);
+    } else {
+        /* being called from user space */
+        if ((err = copyin(CAST_USER_ADDR_T(ctlbuf.buf), (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) {
+            gbuf_freem(mioc);
+            goto l_err;
+        }
+    }
 
-       iocbp = (ioc_t *)gbuf_rptr(mioc);
-       primitives = (union asp_primitives *)gbuf_rptr(mioc);
-       Primitive = primitives->Primitive;
+    iocbp = (ioc_t *)gbuf_rptr(mioc);
+    primitives = (union asp_primitives *)gbuf_rptr(mioc);
+    Primitive = primitives->Primitive;
        dPrintf(D_M_ASP, D_L_INFO,
                ("ASPputmsg: %s\n", aspCmdStr(Primitive)));
 
-       /*
-        * allocate buffer and copy in the data content
-        */
-       len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize;
-       if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) {
-               /* error return should not be possible */
-               err = ENOBUFS;
-               gbuf_freem(mioc);
-               goto l_err;
-       }
-       gbuf_wset(mdata,(datbuf.len+len));
-       gbuf_cont(mioc) = mdata;
-       if ((err = copyin((caddr_t)datbuf.buf,
-                         (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) {
-               gbuf_freem(mioc);
-               goto l_err;
-       }
-
-       switch (Primitive) {
-
-       case ASPFUNC_Command:
-       case ASPFUNC_Write:
-       case ASPFUNC_WriteContinue:
-       case ASPFUNC_Attention:
-               /*
-                * build the command/write/write_continue request
-                */
-               wptr = gbuf_rptr(mdata);
-               atpBDS = (struct atpBDS *)wptr;
-               wptr += atpBDSsize;
-               for (i=0; i < ATP_TRESP_MAX; i++) {
-                       *(unsigned long  *)atpBDS[i].bdsBuffAddr = 1;
-                       *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
-               }
-               sd = (struct atp_set_default *)wptr;
-               wptr += sizeof(struct atp_set_default);
-               sd->def_retries = (scb->cmd_retry.retries == -1) ?
-                 ATP_INFINITE_RETRIES : scb->cmd_retry.retries;
-               sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC;
-               sd->def_BDSlen = atpBDSsize;
-               ddp = (at_ddp_t *)wptr;
-               NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
-               ddp->src_node = scb->loc_addr.node;
-               NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
-               ddp->dst_node = scb->rem_addr.node;
-               ddp->dst_socket = scb->rem_addr.socket;
-               UAS_ASSIGN(ddp->checksum, 0);
-               atp = ATP_ATP_HDR(wptr);
-               wptr += TOTAL_ATP_HDR_SIZE;
-               atp->xo = 1;
-               atp->xo_relt = 1;
-               atp->bitmap = 0xff;
-               awp = (asp_word_t *)atp->user_bytes;
-               awp->func = (unsigned char)Primitive;
-               awp->param1 = scb->sess_id;
-               awp->param2 = scb->snd_seq_num;
-               iocbp->ioc_private = (void *)scb;
-               iocbp->ioc_count = gbuf_len(mdata);
-               iocbp->ioc_rval = 0;
-               iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
-
-               /*
-                * send the command/write/write_continue/attention request
-                */
-               ATDISABLE(s, scb->lock);
-               switch (awp->func) {
-               case ASPFUNC_Command:
-                       scb->state = ASPSTATE_WaitingForCommandRsp;
-                       break;
-               case ASPFUNC_Write:
-                       scb->state = ASPSTATE_WaitingForWriteRsp;
-                       break;
-               case ASPFUNC_WriteContinue:
-                       scb->state = ASPSTATE_WaitingForWriteContinueRsp;
-                       awp->param2 = scb->wrt_seq_num;
-                       break;
-               case ASPFUNC_Attention:
-                       scb->state = ASPSTATE_WaitingForCommandRsp;
-                       atp->xo = 0;
-                       atp->xo_relt = 0;
-                       atp->bitmap = 0x01;
-                       gbuf_wdec(mdata,2);
-                       awp->param2 = *(unsigned short *)gbuf_wptr(mdata);
-                       break;
-               }
-               ATENABLE(s, scb->lock);
-               dPrintf(D_M_ASP,D_L_INFO,
-                       ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
-                        (awp->func == ASPFUNC_Command ? "CommandReq" :
-                         awp->func == ASPFUNC_Write ? "WriteReq" :
-                         awp->func == ASPFUNC_WriteContinue ? "WriteContinue" :
-                         "AttentionReq"),scb->loc_addr.socket,
-                        NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket));
-               atp_send_req(gref, mioc);
-               return 0;
-
-       case ASPFUNC_CmdReply:
-
-               ATDISABLE(s, scb->lock);
-               if (scb->req_msgq) {
-                       mx = scb->req_msgq;
-                       scb->req_msgq = gbuf_next(mx);
-                       gbuf_next(mx) = 0;
-                       ATENABLE(s, scb->lock);
-                       asp_putnext(scb->gref, mx);
-               } else {
-                       scb->req_flag = 0;
-                       ATENABLE(s, scb->lock);
-               }
-               result = primitives->CmdReplyReq.CmdResult;
-               tid = primitives->CmdReplyReq.ReqRefNum;
-
-               /* Re-use the original mioc mbuf to send the response. */
-               gbuf_rinc(mioc,sizeof(void *));
-               gbuf_wset(mioc,0);
-               ddp = (at_ddp_t *)gbuf_wptr(mioc);
-               gbuf_winc(mioc,DDP_X_HDR_SIZE);
-               atp = (at_atp_t *)gbuf_wptr(mioc);
-               gbuf_winc(mioc,ATP_HDR_SIZE);
-               NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
-               ddp->src_node = scb->loc_addr.node;
-               NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
-               ddp->dst_node = scb->rem_addr.node;
-               ddp->dst_socket = scb->reply_socket;
-               ddp->type = DDP_ATP;
-               UAS_ASSIGN(ddp->checksum, 0);
-               UAS_ASSIGN(atp->tid, tid);
-               if (scb->attn_flag && (tid == scb->attn_tid)) {
-                       scb->attn_flag = 0;
-                       atp->xo = 0;
-                       atp->xo_relt = 0;
-               } else {
-                       atp->xo = 1;
-                       atp->xo_relt = 1;
+    /*
+     * 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.
+     */
+         
+    /* 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;  
+    }  
+    
+    /* 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, 0);               /* init length to zero */
+    gbuf_cont(mioc) = mdata;
+
+       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;
                }
-               atpBDS = (struct atpBDS *)gbuf_wptr(mioc);
-               msize = mdata ? gbuf_msgsize(mdata) : 0;
-               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);
+               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;
+                       }
                }
-               UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds);
-               *(long *)atpBDS[0].bdsUserData = (long)result;
-               *(long *)atp->user_bytes = (long)result;
-               gbuf_winc(mioc,atpBDSsize);
+       }
+       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:
+    case ASPFUNC_WriteContinue:
+    case ASPFUNC_Attention:
+        /*
+         * build the command/write/write_continue request
+         */
+        wptr = (unsigned char *)gbuf_rptr(mdata);
+        atpBDS = (struct atpBDS *)wptr;
+        wptr += atpBDSsize;
+        for (i=0; i < ATP_TRESP_MAX; i++) {
+            *(unsigned long  *)atpBDS[i].bdsBuffAddr = 1;
+            *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE;
+        }
+        sd = (struct atp_set_default *)wptr;
+        wptr += sizeof(struct atp_set_default);
+        sd->def_retries = (scb->cmd_retry.retries == -1) ?
+          ATP_INFINITE_RETRIES : scb->cmd_retry.retries;
+        sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC;
+        sd->def_BDSlen = atpBDSsize;
+        ddp = (at_ddp_t *)wptr;
+        NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
+        ddp->src_node = scb->loc_addr.node;
+        NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
+        ddp->dst_node = scb->rem_addr.node;
+        ddp->dst_socket = scb->rem_addr.socket;
+        UAS_ASSIGN(ddp->checksum, 0);
+        atp = ATP_ATP_HDR(wptr);
+        wptr += TOTAL_ATP_HDR_SIZE;
+        atp->xo = 1;
+        atp->xo_relt = 1;
+        atp->bitmap = 0xff;
+        awp = (asp_word_t *)atp->user_bytes;
+        awp->func = (unsigned char)Primitive;
+        awp->param1 = scb->sess_id;
+        awp->param2 = htons(scb->snd_seq_num);
+        iocbp->ioc_private = (void *)scb;
+        iocbp->ioc_count = gbuf_len(mdata);
+        iocbp->ioc_rval = 0;
+        iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF;
+
+        /*
+         * send the command/write/write_continue/attention request
+         */
+        switch (awp->func) {
+        case ASPFUNC_Command:
+            scb->state = ASPSTATE_WaitingForCommandRsp;
+            break;
+        case ASPFUNC_Write:
+            scb->state = ASPSTATE_WaitingForWriteRsp;
+            break;
+        case ASPFUNC_WriteContinue:
+            scb->state = ASPSTATE_WaitingForWriteContinueRsp;
+            awp->param2 = htons(scb->wrt_seq_num);
+            break;
+        case ASPFUNC_Attention:
+            scb->state = ASPSTATE_WaitingForCommandRsp;
+            atp->xo = 0;
+            atp->xo_relt = 0;
+            atp->bitmap = 0x01;
+            gbuf_wdec(mdata,2);
+            awp->param2 = htons(*(unsigned short *)gbuf_wptr(mdata));
+            break;
+        }
+        dPrintf(D_M_ASP,D_L_INFO,
+            ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n",
+             (awp->func == ASPFUNC_Command ? "CommandReq" :
+              awp->func == ASPFUNC_Write ? "WriteReq" :
+              awp->func == ASPFUNC_WriteContinue ? "WriteContinue" :
+              "AttentionReq"),scb->loc_addr.socket,
+             NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket));
+        atp_send_req(gref, mioc);
+        return 0;
+
+    case ASPFUNC_CmdReply:
+
+        if (scb->req_msgq) {
+            mx = scb->req_msgq;
+            scb->req_msgq = gbuf_next(mx);
+            gbuf_next(mx) = 0;
+            asp_putnext(scb->gref, mx);
+        } else
+            scb->req_flag = 0;
+
+        result = primitives->CmdReplyReq.CmdResult;
+        tid = primitives->CmdReplyReq.ReqRefNum;
+
+        /* Re-use the original mioc mbuf to send the response. */
+        gbuf_rinc(mioc,sizeof(void *));
+        gbuf_wset(mioc,0);
+        ddp = (at_ddp_t *)gbuf_wptr(mioc);
+        gbuf_winc(mioc,DDP_X_HDR_SIZE);
+        atp = (at_atp_t *)gbuf_wptr(mioc);
+        gbuf_winc(mioc,ATP_HDR_SIZE);
+        NET_ASSIGN(ddp->src_net, scb->loc_addr.net);
+        ddp->src_node = scb->loc_addr.node;
+        NET_ASSIGN(ddp->dst_net, scb->rem_addr.net);
+        ddp->dst_node = scb->rem_addr.node;
+        ddp->dst_socket = scb->reply_socket;
+        ddp->type = DDP_ATP;
+        UAS_ASSIGN(ddp->checksum, 0);
+        UAS_ASSIGN(atp->tid, htons(tid));
+        if (scb->attn_flag && (tid == scb->attn_tid)) {
+           scb->attn_flag = 0;
+            atp->xo = 0;
+            atp->xo_relt = 0;
+        } else {
+            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++) {
+            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);
+        *(long *)atpBDS[0].bdsUserData = (long)result;
+        *(long *)atp->user_bytes = (long)result;
+        gbuf_winc(mioc,atpBDSsize);
                dPrintf(D_M_ASP, D_L_INFO,
                        ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n",
                         scb->loc_addr.socket, aspStateStr(scb->state), 
                         (mdata ? gbuf_msgsize(mdata) : 0), result, tid));
-               atp_send_rsp(gref, mioc, TRUE);
-               return 0;
-       }
+        atp_send_rsp(gref, mioc, TRUE);
+        return 0;
+    }
 
-       /* Not an expected ASPFUNC */
-       gbuf_freem(mioc);
-       err = EOPNOTSUPP;
+    /* Not an expected ASPFUNC */
+    gbuf_freem(mioc);
+    err = EOPNOTSUPP;
 
 l_err:
-       *errp = err;
-       return -1;
+    *errp = err;
+    return -1;
 } /* ASPputmsg */
 
-int
-ASPgetmsg(gref, ctlptr, datptr, flags, errp)
-       gref_t *gref;
-       strbuf_t *ctlptr;
-       strbuf_t *datptr;
-       int *flags;
-       int *errp;
-{
-       int err, s, len, sum, rval;
-       gbuf_t *mproto, *mdata;
-       strbuf_t ctlbuf;
-       strbuf_t datbuf;
-       asp_scb_t *scb;
-       unsigned char get_wait;
 
-       if ((scb = (asp_scb_t *)gref->info) == 0) {
+/* bms:  make this callable from kernel.  reply date is passed back as a mbuf chain in *mreply  */
+int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, __unused int *flags, int *errp)
+{
+    int err, len, sum, rval;
+    gbuf_t *mproto, *mdata;
+    strbuf_t ctlbuf;
+    strbuf_t datbuf;
+    asp_scb_t *scb;
+    unsigned char get_wait;
+
+    if ((scb = (asp_scb_t *)gref->info) == 0) {
                dPrintf(D_M_ASP, D_L_ERROR,
                        ("ASPgetmsg: stale handle=0x%x, pid=%d\n",
                        (u_int) gref, gref->pid));
@@ -2161,138 +2169,145 @@ ASPgetmsg(gref, ctlptr, datptr, flags, errp)
                return -1;
        }
 
-       ATDISABLE(s, scb->lock);
-       if (scb->state == ASPSTATE_Close) {
-               ATENABLE(s, scb->lock);
-               return 0;
-       }
-
-       /*
-        * get receive data
-        */
-       while ((mproto = scb->sess_ioc) == 0) {
-               scb->get_wait = 1;
-               err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0);
-               if (err != 0) {
-                       scb->get_wait = 0;
-                       ATENABLE(s, scb->lock);
-                       *errp = err;
-                       return -1;
-               }
-               if (scb->state == ASPSTATE_Close) {
-                       scb->get_wait = 0;
-                       ATENABLE(s, scb->lock);
-                       return 0;
-               }
-       }
-       get_wait = scb->get_wait;
-       scb->get_wait = 0;
-       if ((ctlptr == 0) && (datptr == 0)) {
-               ATENABLE(s, scb->lock);
-               return 0;
-       }
-       scb->sess_ioc = gbuf_next(mproto);
-       mdata = gbuf_cont(mproto);
-       ATENABLE(s, scb->lock);
-
-       /* last remaining use of MSG_ERROR */
-       if (gbuf_type(mproto) == MSG_ERROR) {
-               err = (int)gbuf_rptr(mproto)[0];
-               goto l_err;
-       }
-
-       /*
-        * copy in the control and data info
-        */
-       if ((err = copyin((caddr_t)ctlptr,
-                       (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
-               goto l_err;
-       if ((err = copyin((caddr_t)datptr,
-                       (caddr_t)&datbuf, sizeof(datbuf))) != 0)
-               goto l_err;
-       if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) {
-               ATDISABLE(s, scb->lock);
-               gbuf_next(mproto) = scb->sess_ioc;
-               scb->sess_ioc = mproto;
-               ATENABLE(s, scb->lock);
-               return MOREDATA;
-       }
-
-       if (get_wait == 0) {
-               /*
-                * this is a hack to support the select() call.
-                * we're not supposed to dequeue messages in the Streams 
-                * head's read queue this way; but there is no better way.
-                */
-               ATDISABLE(s, scb->lock);
-               if (scb->sess_ioc == 0) {
-                       ATENABLE(s, scb->lock);
-               } else {
-                       ATENABLE(s, scb->lock);
-                       atalk_notify_sel(gref); 
-               }
-       }
-
-       /*
-        * copy out the control content and info
-        */
-       ctlbuf.len = gbuf_len(mproto);
-       if ((err = copyout((caddr_t)gbuf_rptr(mproto),
-                       (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0)
-               goto l_err;
-       if ((err = copyout((caddr_t)&ctlbuf,
-                       (caddr_t)ctlptr, sizeof(ctlbuf))) != 0)
-               goto l_err;
-
-       /*
-        * copy out the data content and info
-        */
-       for (rval=0, sum=0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) {
-               len = gbuf_len(mdata);
-         if (len) {
-               if ((len + sum) > datbuf.maxlen) {
-                       len = datbuf.maxlen - sum;
-                       rval = MOREDATA;
-               }
-               if ((err = copyout((caddr_t)gbuf_rptr(mdata),
-                               (caddr_t)&datbuf.buf[sum], len)) != 0)
-                       goto l_err;
-               sum += len;
-         }
-       }
-       datbuf.len = sum;
-       if ((err = copyout((caddr_t)&datbuf,
-                       (caddr_t)datptr, sizeof(datbuf))) != 0)
-               goto l_err;
-
-#ifdef APPLETALK_DEBUG
-       if (mproto == 0) 
-               kprintf("ASPgetmsg: null mproto!!!\n");
-#endif
-
-       gbuf_freem(mproto);
-
-       ATDISABLE(s, scb->lock);
-       if (scb->sess_ioc)
-               scb->rcv_cnt--;
-       else {
-               scb->rcv_cnt = 0;
-               scb->snd_stop = 0;
-       }
-       ATENABLE(s, scb->lock);
-       return rval;
+    if (scb->state == ASPSTATE_Close)
+        return 0;
+
+    /*
+     * get receive data
+     */
+    while ((mproto = scb->sess_ioc) == 0) {
+        scb->get_wait = 1;
+          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;
+            *errp = err;
+            return -1;
+        }
+        if (scb->state == ASPSTATE_Close) {
+            scb->get_wait = 0;
+            return 0;
+        }
+    }
+    get_wait = scb->get_wait;
+    scb->get_wait = 0;
+    if ((ctlptr == 0) && (datptr == 0))
+        return 0;
+    scb->sess_ioc = gbuf_next(mproto);
+    mdata = gbuf_cont(mproto);
+
+    /* last remaining use of MSG_ERROR */
+    if (gbuf_type(mproto) == MSG_ERROR) {
+        err = (int)gbuf_rptr(mproto)[0];
+        goto l_err;
+    }
+
+    /*
+     * copy in the control and data info
+     */
+    if (mreply != NULL) {
+        /* called from kernel space */
+        bcopy (ctlptr, &ctlbuf, sizeof(ctlbuf));
+        bcopy (datptr, &datbuf, sizeof(datbuf));
+    } else {
+        /* called from user space */
+        if ((err = copyin(CAST_USER_ADDR_T(ctlptr),
+                (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0)
+            goto l_err;
+        if ((err = copyin(CAST_USER_ADDR_T(datptr),
+                (caddr_t)&datbuf, sizeof(datbuf))) != 0)
+            goto l_err;
+    }
+    if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) {
+        gbuf_next(mproto) = scb->sess_ioc;
+        scb->sess_ioc = mproto;
+        return MOREDATA;
+    }
+
+    if (get_wait == 0) {
+        /*
+         * this is a hack to support the select() call.
+         * we're not supposed to dequeue messages in the Streams 
+         * head's read queue this way; but there is no better way.
+         */
+        if (scb->sess_ioc != 0)
+            atalk_notify_sel(gref); 
+        
+    }
+
+    /*
+     * copy out the control content and info
+     */
+    ctlbuf.len = gbuf_len(mproto);
+
+    if (mreply != NULL) {
+        /* called from kernel space */
+        bcopy (gbuf_rptr(mproto), ctlbuf.buf, ctlbuf.len);
+        bcopy (&ctlbuf, ctlptr, sizeof(ctlbuf));
+    } else {
+        /* called from user space */
+        if ((err = copyout((caddr_t)gbuf_rptr(mproto),
+                CAST_USER_ADDR_T(ctlbuf.buf), ctlbuf.len)) != 0)
+            goto l_err;
+        if ((err = copyout((caddr_t)&ctlbuf,
+                CAST_USER_ADDR_T(ctlptr), sizeof(ctlbuf))) != 0)
+            goto l_err;
+    }
+
+    /*
+     * copy out the data content and info
+     */
+    for (rval = 0, sum = 0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) 
+    {
+        len = gbuf_len(mdata);
+        if (len) {
+            if ((len + sum) > datbuf.maxlen) {
+                len = datbuf.maxlen - sum;
+                rval = MOREDATA;
+            }
+            
+            if (mreply == NULL) {
+                /* called from user space */
+                if ((err = copyout((caddr_t)gbuf_rptr(mdata), CAST_USER_ADDR_T(&datbuf.buf[sum]), len)) != 0)
+                    goto l_err;
+            }
+            sum += len;
+        }
+    }
+    datbuf.len = sum;
+    if (mreply != NULL) {
+        /* called from kernel space */
+        bcopy (&datbuf, datptr, sizeof(datbuf));
+    } else {
+        /* called from user space */
+        if ((err = copyout((caddr_t)&datbuf, CAST_USER_ADDR_T(datptr), sizeof(datbuf))) != 0)
+            goto l_err;
+    }
+    
+    if (mreply != NULL) {
+        /* called from kernel space */
+        /* return the reply data in mbufs, so dont free them.  
+        Just free the proto info */
+        mdata = gbuf_cont(mproto);
+        *mreply = mdata;
+        gbuf_cont(mproto) = NULL;
+        gbuf_freem(mproto);
+    } else {
+        /* called from user space */
+        gbuf_freem(mproto);
+    }
+
+    if (scb->sess_ioc)
+        scb->rcv_cnt--;
+    else {
+        scb->rcv_cnt = 0;
+        scb->snd_stop = 0;
+    }
+    return rval;
 
 l_err:
-       dPrintf(D_M_ASP, D_L_ERROR,
-               ("ASPgetmsg: err=%d, loc=%d, rem=%x.%x.%d, state=%s\n",
-                err, scb->loc_addr.socket, 
-                scb->rem_addr.net,
-                scb->rem_addr.node, scb->rem_addr.socket,
-                aspStateStr(scb->state)));
-       ATDISABLE(s, scb->lock);
-       gbuf_next(mproto) = scb->sess_ioc;
-       scb->sess_ioc = mproto;
-       ATENABLE(s, scb->lock);
-       *errp = err;
-       return -1;
+    gbuf_next(mproto) = scb->sess_ioc;
+    scb->sess_ioc = mproto;
+    *errp = err;
+    return -1;
 }