X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..6d2010ae8f7a6078e10b361c6962983bab233e0f:/bsd/netat/asp_proto.c diff --git a/bsd/netat/asp_proto.c b/bsd/netat/asp_proto.c index a93025454..8f1621b54 100644 --- a/bsd/netat/asp_proto.c +++ b/bsd/netat/asp_proto.c @@ -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 @@ -40,13 +44,14 @@ #include #include #include +#include #include #include #include -#include #include +#include #include #include #include @@ -54,13 +59,6 @@ #include #include -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<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; }