+++ /dev/null
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * 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_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- * Copyright (c) 1995-1998 Apple Computer, Inc.
- * All Rights Reserved.
- */
-
-/*
- * 09/07/95 - Modified for performance (Tuyen Nguyen)
- * Modified for MP, 1996 by Tuyen Nguyen
- * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
- */
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <machine/spl.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/filedesc.h>
-#include <sys/fcntl.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/time.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-
-#include <net/if.h>
-
-#include <netat/sysglue.h>
-#include <netat/appletalk.h>
-#include <netat/ddp.h>
-#include <netat/at_snmp.h>
-#include <netat/at_pcb.h>
-#include <netat/debug.h>
-#include <netat/at_var.h>
-#include <netat/adsp.h>
-#include <netat/adsp_internal.h>
-
-void adsp_rput(gref_t *, gbuf_t *);
-static void adsp_iocack(gref_t *, gbuf_t *);
-static void adsp_iocnak(gref_t *, gbuf_t *, int err);
-void adsp_dequeue_ccb(CCB *);
-int adspInited = 0;
-
-GLOBAL adspGlobal;
-
-/**********/
-
-int adsp_pidM[256];
-char adsp_inputC[256];
-CCB *adsp_inputQ[256];
-
-extern at_ifaddr_t *ifID_home;
-
-CCB *ccb_used_list;
-
-void adsp_input(mp)
- gbuf_t *mp;
-{
- gref_t *gref;
- CCBPtr sp;
- at_ddp_t *p;
- gbuf_t *mb;
-
- switch (gbuf_type(mp)) {
- case MSG_DATA:
- p = (at_ddp_t *)gbuf_rptr(mp);
- sp = adsp_inputQ[p->dst_socket];
- if ((sp == 0) || (sp->gref==0) || (sp->state==sClosed))
- {
- gbuf_freem(mp);
- return;
- }
- else if (sp->otccbLink != 0) {
- do {
- if ((sp->remoteAddress.a.node == p->src_node)
- && (sp->remoteAddress.a.socket == p->src_socket)
- && (sp->remoteAddress.a.net == NET_VALUE(p->src_net)))
- break;
- } while ((sp = sp->otccbLink) != 0);
- if (sp == 0)
- {
- gbuf_freem(mp);
- return;
- }
- }
- if (sp->lockFlag) {
- gbuf_next(mp) = 0;
- if (sp->deferred_mb) {
- for (mb=sp->deferred_mb; gbuf_next(mb); mb=gbuf_next(mb)) ;
- gbuf_next(mb) = mp;
- } else
- sp->deferred_mb = mp;
- return;
- }
- sp->lockFlag = 1;
- while (mp) {
- adsp_rput(sp->gref, mp);
- if ((mp = sp->deferred_mb) != 0) {
- sp->deferred_mb = gbuf_next(mp);
- gbuf_next(mp) = 0;
- }
- }
- sp->lockFlag = 0;
- return;
-
- case MSG_IOCACK:
- case MSG_IOCNAK:
- gref = (gref_t *)((ioc_t *)gbuf_rptr(mp))->ioc_private;
- break;
-
- case MSG_IOCTL:
-#ifdef APPLETALK_DEBUG
- kprintf("unexpected MSG_IOCTL in adsp_input()");
-#endif
- /* fall through */
-
- default:
- gbuf_freem(mp);
- return;
- }
-
- adsp_rput(gref, mp);
-}
-
-/**********/
-int adsp_readable(gref_t *);
-
-int adsp_readable(gref)
- gref_t *gref;
-{
- int rc;
- CCBPtr sp;
-
- if (gref->info == 0)
- /*
- * we don't have the structure we need to determine
- * if there's data available... we return readable in
- * this case to keep from hanging up in the select
- * a subsequent read will run into the same missing data
- * structure and return an error... the ATselect code does
- * this if it can't retrieve the 'gref' structure from the
- * file table for the fd specified
- */
- return(1);
-
- sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- rc = sp->rData;
-
- return rc;
-}
-
-int adsp_writeable(gref_t *);
-int adsp_writeable(gref)
- gref_t *gref;
-{
- int rc;
- CCBPtr sp;
-
- if (gref->info == 0)
- /*
- * we don't have the structure we need to determine
- * if there's room available... we return writeable in
- * this case to keep from hanging up in the select
- * a subsequent write will run into the same missing data
- * structure and return an error... the ATselect code does
- * this if it can't retrieve the 'gref' structure from the
- * file table for the fd specified
- */
- return(1);
-
- sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- rc = CalcSendQFree(sp);
-
- return rc;
-}
-
-static void adsp_init(void);
-
-static void adsp_init(void)
-{
- adspInited++;
- InitGlobals();
- ccb_used_list = 0;
- bzero(adsp_pidM, sizeof(adsp_pidM));
- bzero(adsp_inputC, sizeof(adsp_inputC));
- bzero(adsp_inputQ, sizeof(adsp_inputQ));
-}
-
-/*
- * Description:
- * ADSP open and close routines. These routines
- * initalize and release the ADSP structures. They do not
- * have anything to do with "connections"
- */
-
-int adsp_open(gref)
- gref_t *gref;
-{
- register CCBPtr sp;
-
- if (!adspInited)
- adsp_init();
-
- if (!adspAllocateCCB(gref))
- return(ENOBUFS); /* can't get buffers */
-
- sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- gref->readable = adsp_readable;
- gref->writeable = adsp_writeable;
- if ((sp->otccbLink = ccb_used_list) != 0)
- sp->otccbLink->ccbLink = sp;
- ccb_used_list = sp;
- return 0;
-}
-
-int adsp_close(gref)
- gref_t *gref;
-{
- unsigned char localSocket;
-
- /* make sure we've not yet removed the CCB (e.g., due to TrashSession) */
- if (gref->info) {
- CCBPtr sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- localSocket = sp->localSocket;
- if (localSocket)
- adspRelease(gref);
- else
- {
- adsp_dequeue_ccb(sp);
- gbuf_freeb((gbuf_t *)gref->info);
- }
- }
- return 0;
-}
-
-
-/*
- * Name:
- * adsp_rput
- *
- * Description:
- * ADSP streams read put and service routines.
- */
-
-void adsp_rput(gref, mp)
- gref_t *gref; /* READ queue */
- gbuf_t *mp;
-{
- switch (gbuf_type(mp)) {
- case MSG_HANGUP:
- case MSG_IOCACK:
- case MSG_IOCNAK:
- switch (adspReadHandler(gref, mp)) {
- case STR_PUTNEXT:
- atalk_putnext(gref, mp);
- break;
- case STR_IGNORE:
- break;
- }
- break;
- case MSG_ERROR:
-#ifdef APPLETALK_DEBUG
- kprintf("adsp_rput received MSG_ERROR");
-#endif
- /* fall through */
- default:
- CheckReadQueue((CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)));
- CheckSend((CCBPtr)gbuf_rptr(((gbuf_t *)gref->info)));
-
- switch (gbuf_type(mp)) {
- case MSG_IOCTL:
- case MSG_DATA:
- case MSG_PROTO:
- if (adspReadHandler(gref, mp) == STR_PUTNEXT)
- atalk_putnext(gref, mp);
- break;
- default:
- atalk_putnext(gref, mp);
- break;
- }
- }
-}
-
-/*
- * Name:
- * adsp_wput
- *
- * Description:
- * ADSP streams write put and service routines.
- *
- */
-
-int adsp_wput(gref, mp)
- gref_t *gref; /* WRITE queue */
- gbuf_t *mp;
-{
- int rc;
- gbuf_t *xm;
- ioc_t *iocbp;
- CCBPtr sp;
-
- if (gref->info)
- sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- else
- sp = 0;
-
- if (gbuf_type(mp) == MSG_IOCTL) {
- iocbp = (ioc_t *)gbuf_rptr(mp);
- switch (iocbp->ioc_cmd) {
- case ADSPBINDREQ:
- {
- unsigned char v;
-
- if (gbuf_cont(mp) == NULL) {
- iocbp->ioc_rval = -1;
- adsp_iocnak(gref, mp, EINVAL);
- }
- v = *(unsigned char *)gbuf_rptr(gbuf_cont(mp));
- if ( (v != 0)
- && ((v > DDP_SOCKET_LAST) || (v < 2)
- || ddp_socket_inuse(v, DDP_ADSP))) {
- iocbp->ioc_rval = -1;
- adsp_iocnak(gref, mp, EINVAL);
- }
- else {
- if (v == 0) {
- if ((v = adspAssignSocket(gref, 0)) == 0) {
- iocbp->ioc_rval = -1;
- adsp_iocnak(gref, mp, EINVAL);
- return 0;
- }
- } else {
- adsp_inputC[v] = 1;
- adsp_inputQ[v] = sp;
- adsp_pidM[v] = sp->pid;
- adsp_dequeue_ccb(sp);
- }
- *(unsigned char *)gbuf_rptr(gbuf_cont(mp)) = v;
- sp->localSocket = v;
- iocbp->ioc_rval = 0;
- adsp_iocack(gref, mp);
- }
- return 0;
- }
-
- case ADSPGETSOCK:
- case ADSPGETPEER:
- {
- at_inet_t *addr;
-
- if (((xm = gbuf_cont(mp)) == NULL)
- && ((xm = gbuf_alloc(sizeof(at_inet_t), PRI_MED)) == NULL)) {
- iocbp->ioc_rval = -1;
- adsp_iocnak(gref, mp, ENOBUFS);
- return 0;
- }
- gbuf_cont(mp) = xm;
- gbuf_wset(xm,sizeof(at_inet_t));
- addr = (at_inet_t *)gbuf_rptr(xm);
- if (iocbp->ioc_cmd == ADSPGETSOCK) {
- /* Obtain Network and Node Id's from DDP */
- /* *** was ddp_get_cfg() *** */
- addr->net = ifID_home->ifThisNode.s_net;
- addr->node = ifID_home->ifThisNode.s_node;
- addr->socket = (sp)? sp->localSocket: 0;
- } else
- if (sp)
- *addr = sp->remoteAddress.a;
- else {
- addr->net = 0;
- addr->node = 0;
- addr->socket = 0;
- }
- iocbp->ioc_rval = 0;
- adsp_iocack(gref, mp);
- return 0;
- }
- case DDP_IOC_GET_CFG:
- /* respond to an DDP_IOC_GET_CFG sent on an adsp fd */
- if (((xm = gbuf_cont(mp)) == NULL) &&
- (xm = gbuf_alloc(sizeof(ddp_addr_t), PRI_MED)) == NULL) {
- iocbp->ioc_rval = -1;
- adsp_iocnak(gref, mp, ENOBUFS);
- return 0;
- }
- gbuf_cont(mp) = xm;
- gbuf_wset(xm, sizeof(ddp_addr_t));
- /* Obtain Network and Node Id's from DDP */
- {
- /* *** was ddp_get_cfg() *** */
- ddp_addr_t *cfgp =
- (ddp_addr_t *)gbuf_rptr(gbuf_cont(mp));
- cfgp->inet.net = ifID_home->ifThisNode.s_net;
- cfgp->inet.node = ifID_home->ifThisNode.s_node;
- cfgp->inet.socket = (sp)? sp->localSocket: 0;
- cfgp->ddptype = DDP_ADSP;
- }
- iocbp->ioc_rval = 0;
- adsp_iocack(gref, mp);
- return 0;
- } /* switch */
- }
-
- if (!gref->info)
- gbuf_freem(mp);
- else {
- rc = adspWriteHandler(gref, mp);
-
- switch (rc) {
- case STR_PUTNEXT:
- if (gbuf_type(mp) == MSG_IOCTL) {
- iocbp = (ioc_t *)gbuf_rptr(mp);
- iocbp->ioc_private = (void *)gref;
- }
- DDP_OUTPUT(mp);
- break;
- case STR_IGNORE:
- case STR_IGNORE+99:
- break;
- default:
- gbuf_freem(mp);
- break;
- }
- }
-
- return 0;
-} /* adsp_wput */
-
-void adspioc_ack(errno, m, gref)
- int errno;
- gbuf_t *m;
- gref_t *gref;
-{
- ioc_t *iocbp;
-
- if (m == NULL)
- return;
- iocbp = (ioc_t *) gbuf_rptr(m);
-
- iocbp->ioc_error = errno; /* set the errno */
- iocbp->ioc_count = gbuf_msgsize(gbuf_cont(m));
- if (gbuf_type(m) == MSG_IOCTL) /* if an ioctl, this is an ack */
- gbuf_set_type(m, MSG_IOCACK); /* and ALWAYS update the user */
- /* ioctl structure */
- trace_mbufs(D_M_ADSP,"A ", m);
- SndMsgUp(gref, m);
-}
-
-static void adsp_iocack(gref, m)
- gref_t *gref;
- register gbuf_t *m;
-{
- if (gbuf_type(m) == MSG_IOCTL)
- gbuf_set_type(m, MSG_IOCACK);
-
- if (gbuf_cont(m))
- ((ioc_t *)gbuf_rptr(m))->ioc_count = gbuf_msgsize(gbuf_cont(m));
- else
- ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
-
- SndMsgUp(gref, m);
-}
-
-
-static void adsp_iocnak(gref, m, err)
- gref_t *gref;
- register gbuf_t *m;
- register int err;
-{
- if (gbuf_type(m) == MSG_IOCTL)
- gbuf_set_type(m, MSG_IOCNAK);
- ((ioc_t *)gbuf_rptr(m))->ioc_count = 0;
-
- if (err == 0)
- err = ENXIO;
- ((ioc_t *)gbuf_rptr(m))->ioc_error = err;
-
- if (gbuf_cont(m)) {
- gbuf_freem(gbuf_cont(m));
- gbuf_cont(m) = NULL;
- }
- SndMsgUp(gref, m);
-}
-
-unsigned char
-adspAssignSocket(gref, flag)
- gref_t *gref;
- int flag;
-{
- unsigned char sVal, sMax, sMin, sSav = 0, inputC;
- CCBPtr sp;
-
- sMax = flag ? DDP_SOCKET_LAST-46 : DDP_SOCKET_LAST-6;
- sMin = DDP_SOCKET_1st_DYNAMIC;
-
- for (inputC=255, sVal=sMax; sVal >= sMin; sVal--) {
- if (!ddp_socket_inuse(sVal, DDP_ADSP))
- break;
- else if (flag) {
- if (adsp_inputC[sVal] &&
- /* meaning that raw DDP doesn't have it */
- (adsp_inputC[sVal] < inputC)
- && (adsp_inputQ[sVal]->state == sOpen)) {
- inputC = adsp_inputC[sVal];
- sSav = sVal;
- }
- }
- }
- if (sVal < sMin) {
- if (!flag || (inputC == 255))
- return 0;
- sVal = sSav;
- }
- sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
- adsp_dequeue_ccb(sp);
- adsp_inputC[sVal]++;
- sp->otccbLink = adsp_inputQ[sVal];
- adsp_inputQ[sVal] = sp;
- if (!flag)
- adsp_pidM[sVal] = sp->pid;
- return sVal;
-}
-
-int
-adspDeassignSocket(sp)
- CCBPtr sp;
-{
- unsigned char sVal;
- CCBPtr curr_sp;
- CCBPtr prev_sp;
- int pid = 0;
-
- dPrintf(D_M_ADSP, D_L_TRACE, ("adspDeassignSocket: pid=%d,s=%d\n",
- sp->pid, sp->localSocket));
- sVal = sp->localSocket;
- if ((curr_sp = adsp_inputQ[sVal]) != 0) {
- prev_sp = 0;
- while (curr_sp != sp) {
- prev_sp = curr_sp;
- curr_sp = curr_sp->otccbLink;
- }
- if (curr_sp) {
- if (prev_sp)
- prev_sp->otccbLink = sp->otccbLink;
- else
- adsp_inputQ[sVal] = sp->otccbLink;
- if (adsp_inputQ[sVal])
- adsp_inputC[sVal]--;
- else {
- pid = adsp_pidM[sVal];
- adsp_inputC[sVal] = 0;
- adsp_pidM[sVal] = 0;
- }
- sp->ccbLink = 0;
- sp->otccbLink = 0;
- sp->localSocket = 0;
- return pid ? 0 : 1;
- }
- }
-
- dPrintf(D_M_ADSP, D_L_ERROR,
- ("adspDeassignSocket: closing, no CCB block, trouble ahead\n"));
- return -1;
-} /* adspDeassignSocket */
-
-/*
- * remove CCB from the use list
- */
-void
-adsp_dequeue_ccb(sp)
- CCB *sp;
-{
-
- if (sp == ccb_used_list) {
- if ((ccb_used_list = sp->otccbLink) != 0)
- sp->otccbLink->ccbLink = 0;
- } else if (sp->ccbLink) {
- if ((sp->ccbLink->otccbLink = sp->otccbLink) != 0)
- sp->otccbLink->ccbLink = sp->ccbLink;
- }
-
- sp->otccbLink = 0;
- sp->ccbLink = 0;
-}
-
-void SndMsgUp(gref, mp)
- gref_t *gref; /* WRITE queue */
- gbuf_t *mp;
-{
-/*
- dPrintf(D_M_ADSP, D_L_TRACE,
- ("SndMsgUp: gref=0x%x, mbuf=0x%x\n", (unsigned)gref, (unsigned)mp));
- trace_mbufs(D_M_ADSP, " m", mp);
-*/
- atalk_putnext(gref, mp);
-}