X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/de355530ae67247cbd0da700edb3a2a1dae884c2..8ad349bb6ed4a0be06e34c92be0d98b92e078db4:/bsd/netat/asp_proto.c?ds=sidebyside diff --git a/bsd/netat/asp_proto.c b/bsd/netat/asp_proto.c index c495412de..4fd149125 100644 --- a/bsd/netat/asp_proto.c +++ b/bsd/netat/asp_proto.c @@ -1,23 +1,31 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. * - * This 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. + * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ * - * @APPLE_LICENSE_HEADER_END@ + * 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. + * + * 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, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ */ /* * Copyright (c) 1995 Apple Computer, Inc. @@ -40,6 +48,7 @@ #include #include #include +#include #include #include @@ -81,11 +90,10 @@ void asp_init(); void asp_ack_reply(); void asp_nak_reply(); void asp_clock(); -void asp_clock_funnel(); +void asp_clock_locked(void *); int asp_open(); int asp_close(); int asp_wput(); -void atp_retry_req(); StaticProc asp_scb_t *asp_find_scb(); StaticProc asp_scb_t *asp_scb_alloc(); @@ -98,13 +106,14 @@ StaticProc void asp_timout(); StaticProc void asp_untimout(); StaticProc void asp_hangup(); StaticProc void asp_send_tickle(); -StaticProc void asp_send_tickle_funnel(); +StaticProc void asp_send_tickle_locked(void *); StaticProc void asp_accept(); StaticProc int asp_send_req(); extern at_ifaddr_t *ifID_home; extern int atp_pidM[]; extern gref_t *atp_inputQ[]; +extern lck_mtx_t *atalk_mutex; gbuf_t *scb_resource_m = 0; unsigned char asp_inpC[256]; asp_scb_t *asp_scbQ[256]; @@ -266,7 +275,7 @@ asp_close(gref) */ scb->tmo_cnt = 0; asp_untimout(asp_hangup, scb); - untimeout(asp_send_tickle_funnel, (void *)scb); /* added for 2225395 */ + untimeout(asp_send_tickle_locked, (void *)scb); /* added for 2225395 */ /* * free the asp session control block @@ -371,7 +380,7 @@ void trace_end(str) dPrintf(D_M_ASP, D_L_TRACE, (" %s: %s\n", str, mbuf_totals())); } -#endif AT_MBUF_TRACE +#endif /* AT_MBUF_TRACE */ /* * the write routine @@ -494,7 +503,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 +511,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 +519,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 +528,11 @@ int asp_wput(gref, m) server_scb = asp_scbQ[addr->socket]; /*### LD 10/28/97: changed to make sure we're not accessing a null server_scb */ if (server_scb == 0) { - asp_iocnak(gref, mioc, EPROTO); + asp_iocnak(gref, mioc, EPROTOTYPE); return 0; } if (server_scb->sess_ioc == 0) { - asp_iocnak(gref, mioc, EPROTO); + asp_iocnak(gref, mioc, EPROTOTYPE); return 0; } @@ -659,7 +668,7 @@ int asp_wput(gref, m) { struct atp_state *atp = (struct atp_state *)gref->info; if (atp->dflag) - atp = atp->atp_msgq; + atp = (struct atp_state *)atp->atp_msgq; if (gbuf_cont(mioc) == 0) { asp_iocnak(gref, mioc, EINVAL); @@ -775,15 +784,15 @@ asp_send_req(gref, mioc, dest, retry, awp, xo, state, bitmap) } /* - * send tickle routine - funnelled version + * send tickle routine - locked version */ StaticProc void -asp_send_tickle_funnel(scb) - asp_scb_t *scb; +asp_send_tickle_locked(scb) + void *scb; { - thread_funnel_set(network_flock, TRUE); - asp_send_tickle(scb); - thread_funnel_set(network_flock, FALSE); + atalk_lock(); + asp_send_tickle((asp_scb_t *)scb); + atalk_unlock(); } @@ -811,7 +820,7 @@ asp_send_tickle(scb) dPrintf(D_M_ASP, D_L_WARNING, ("asp_send_tickle: ENOBUFS 0, loc=%d, rem=%d\n", scb->loc_addr.socket,scb->rem_addr.socket)); - timeout(asp_send_tickle_funnel, (void *)scb, 10); + timeout(asp_send_tickle_locked, (void *)scb, 10); return; } gbuf_wset(mioc,sizeof(ioc_t)); @@ -833,7 +842,7 @@ asp_send_tickle(scb) ("asp_send_tickle: ENOBUFS 1, loc=%d, rem=%d\n", scb->loc_addr.socket,scb->rem_addr.socket)); - timeout(asp_send_tickle_funnel, (void *)scb, 10); + timeout(asp_send_tickle_locked, (void *)scb, 10); return; } } @@ -894,14 +903,14 @@ asp_accept(scb, sess_scb, m) } /* asp_accept */ /* - * timer routine - funneled version + * timer routine - locked version */ -void asp_clock_funnel(arg) +void asp_clock_locked(arg) void *arg; { - thread_funnel_set(network_flock, TRUE); + atalk_lock(); asp_clock(arg); - thread_funnel_set(network_flock, FALSE); + atalk_unlock(); } /* @@ -930,7 +939,7 @@ void asp_clock(arg) ATENABLE(s, asptmo_lock); if (++scb_tmo_cnt == 0) scb_tmo_cnt++; - timeout(asp_clock_funnel, (void *)arg, (1<info) == 0) { dPrintf(D_M_ASP, D_L_ERROR, @@ -1953,9 +1963,9 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in bcopy (datptr, &datbuf, sizeof (strbuf_t)); } else { /* being called from user space */ - if ((err = copyin((caddr_t)ctlptr, (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) + if ((err = copyin(CAST_USER_ADDR_T(ctlptr), (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) goto l_err; - if ((err = copyin((caddr_t)datptr, (caddr_t)&datbuf, sizeof(datbuf))) != 0) + if ((err = copyin(CAST_USER_ADDR_T(datptr), (caddr_t)&datbuf, sizeof(datbuf))) != 0) goto l_err; } @@ -1975,7 +1985,7 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in bcopy (ctlbuf.buf, gbuf_rptr(mioc), ctlbuf.len); } else { /* being called from user space */ - if ((err = copyin((caddr_t)ctlbuf.buf, (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) { + if ((err = copyin(CAST_USER_ADDR_T(ctlbuf.buf), (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) { gbuf_freem(mioc); goto l_err; } @@ -1988,46 +1998,77 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in ("ASPputmsg: %s\n", aspCmdStr(Primitive))); /* - * allocate buffer and copy in the data content + * copy in the data content into multiple mbuf clusters if + * required. ATP now expects reply data to be placed in + * standard clusters, not the large external clusters that + * were used previously. */ - len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize; + + /* set offset for use by some commands */ + offset = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize; + size = 0; + if (mreq != NULL) { + /* The data from the in-kernel call for use by AFP is passed + * in as one large external cluster. This needs to be copied + * to a chain of standard clusters. + */ + remain = gbuf_len(mreq); + dataptr = mtod(mreq, caddr_t); + } else { + /* copyin from user space */ + remain = datbuf.len; + dataptr = (caddr_t)datbuf.buf; + } - if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) { + /* allocate first buffer */ + if (!(mdata = gbuf_alloc_wait((remain + offset > MCLBYTES ? MCLBYTES : remain + offset), TRUE))) { /* error return should not be possible */ err = ENOBUFS; gbuf_freem(mioc); goto l_err; } - gbuf_wset(mdata, (datbuf.len+len)); + gbuf_wset(mdata, 0); /* init length to zero */ gbuf_cont(mioc) = mdata; - - if (mreq != NULL) { - /* being called from kernel space */ - gbuf_t *tmp = mreq; - unsigned long offset = 0; - - /* copy afp cmd data from the passed in mbufs to mdata. I cant - chain mreq to mdata since the rest of this code assumes - just one big mbuf with space in front for the BDS */ - offset = len; - while (tmp != NULL) { - bcopy (gbuf_rptr(tmp), (gbuf_rptr(mdata) + offset), gbuf_len(tmp)); - offset += gbuf_len(tmp); - tmp = gbuf_cont(tmp); /* on to next mbuf in chain */ - } - - /* all data copied out of mreq so free it */ - gbuf_freem(mreq); - } else { - /* being called from user space */ - if ((err = copyin((caddr_t)datbuf.buf, - (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) { - gbuf_freem(mioc); - goto l_err; - } - } - switch (Primitive) { + while (remain) { + if (remain + offset > MCLBYTES) + copy_len = MCLBYTES - offset; + else + copy_len = remain; + remain -= copy_len; + if (mreq != NULL) + bcopy (dataptr, (gbuf_rptr(mdata) + offset), copy_len); + else if ((err = copyin(CAST_USER_ADDR_T(dataptr), (caddr_t)(gbuf_rptr(mdata) + offset), copy_len)) != 0) { + gbuf_freem(mioc); + goto l_err; + } + gbuf_wset(mdata, (copy_len + offset)); + size += copy_len + offset; + dataptr += copy_len; + offset = 0; + if (remain) { + /* allocate the next mbuf */ + if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) { + err = ENOBUFS; + gbuf_freem(mioc); + goto l_err; + } + mdata = gbuf_cont(mdata); + MCLGET(mdata, M_WAIT); + if (!(mdata->m_flags & M_EXT)) { + err = ENOBUFS; + gbuf_freem(mioc); + goto l_err; + } + } + } + mdata = gbuf_cont(mioc); /* code further on down expects this to b e set */ + mdata->m_pkthdr.len = size; /* set packet hdr len */ + + if (mreq != 0) + gbuf_freem(mreq); + + switch (Primitive) { case ASPFUNC_Command: case ASPFUNC_Write: @@ -2144,16 +2185,20 @@ int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, in atp->xo = 1; atp->xo_relt = 1; } + /* setup the atpBDS struct - only the length field is used, + * except for the first one which contains the bds count in + * bdsDataSz. + */ atpBDS = (struct atpBDS *)gbuf_wptr(mioc); msize = mdata ? gbuf_msgsize(mdata) : 0; - for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) { + for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) { len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE; msize -= ATP_DATA_SIZE; *(long *)atpBDS[nbds].bdsUserData = 0; UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1); UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len); } - UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds); + UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds); *(long *)atpBDS[0].bdsUserData = (long)result; *(long *)atp->user_bytes = (long)result; gbuf_winc(mioc,atpBDSsize); @@ -2205,7 +2250,8 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, */ while ((mproto = scb->sess_ioc) == 0) { scb->get_wait = 1; - err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0); + lck_mtx_assert(atalk_mutex, LCK_MTX_ASSERT_OWNED); + err = msleep(&scb->event, atalk_mutex, PSOCK | PCATCH, "aspgetmsg", 0); if (err != 0) { scb->get_wait = 0; ATENABLE(s, scb->lock); @@ -2243,10 +2289,10 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, bcopy (datptr, &datbuf, sizeof(datbuf)); } else { /* called from user space */ - if ((err = copyin((caddr_t)ctlptr, + if ((err = copyin(CAST_USER_ADDR_T(ctlptr), (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) goto l_err; - if ((err = copyin((caddr_t)datptr, + if ((err = copyin(CAST_USER_ADDR_T(datptr), (caddr_t)&datbuf, sizeof(datbuf))) != 0) goto l_err; } @@ -2285,10 +2331,10 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, } else { /* called from user space */ if ((err = copyout((caddr_t)gbuf_rptr(mproto), - (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0) + CAST_USER_ADDR_T(ctlbuf.buf), ctlbuf.len)) != 0) goto l_err; if ((err = copyout((caddr_t)&ctlbuf, - (caddr_t)ctlptr, sizeof(ctlbuf))) != 0) + CAST_USER_ADDR_T(ctlptr), sizeof(ctlbuf))) != 0) goto l_err; } @@ -2306,7 +2352,7 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, if (mreply == NULL) { /* called from user space */ - if ((err = copyout((caddr_t)gbuf_rptr(mdata), (caddr_t)&datbuf.buf[sum], len)) != 0) + if ((err = copyout((caddr_t)gbuf_rptr(mdata), CAST_USER_ADDR_T(&datbuf.buf[sum]), len)) != 0) goto l_err; } sum += len; @@ -2318,7 +2364,7 @@ int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, bcopy (&datbuf, datptr, sizeof(datbuf)); } else { /* called from user space */ - if ((err = copyout((caddr_t)&datbuf, (caddr_t)datptr, sizeof(datbuf))) != 0) + if ((err = copyout((caddr_t)&datbuf, CAST_USER_ADDR_T(datptr), sizeof(datbuf))) != 0) goto l_err; }