darwin-xnu/bsd/netat/adsp_Packet.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/* 
  23 * Packet.c 
  24 *
  25 * v01.23  All incoming packets come here first    06/21/90 mbs
  26 *    Modified for MP, 1996 by Tuyen Nguyen
  27 *   Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
  28 */
  29
  30#include <sys/errno.h>
  31#include <sys/types.h>
  32#include <sys/param.h>
  33#include <machine/spl.h>
  34#include <sys/systm.h>
  35#include <sys/kernel.h>
  36#include <sys/proc.h>
  37#include <sys/filedesc.h>
  38#include <sys/fcntl.h>
  39#include <sys/mbuf.h>
  40#include <sys/ioctl.h>
  41#include <sys/malloc.h>
  42#include <sys/socket.h>
  43#include <sys/socketvar.h>
  44#include <sys/time.h>
  45
  46#include <net/if.h>
  47
  48#include <netat/sysglue.h>
  49#include <netat/appletalk.h>
  50#include <netat/at_pcb.h>
  51#include <netat/ddp.h>
  52#include <netat/at_var.h>
  53
  54#include <netat/adsp.h>
  55#include <netat/adsp_internal.h>
  56
  57extern at_ifaddr_t *ifID_home;
  58
  59/*
  60 * GleanSession
  61 *
  62 * We just got a packet for this session, glean its address &
  63 * reset probe timer
  64 *
  65 * INPUTS:
  66 *    Session
  67 * OUTPUTS:
  68 *    none
  69 */
  70static void GleanSession(sp)            /* (CCBPtr sp) */
  71    CCBPtr sp;
  72{
  73    if (sp->openState == O_STATE_OPEN) {
  74        /* This is true for both state = sOpen & sClosing */
  75        RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer);
  76        InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, 
  77                        sp->probeInterval);
  78        sp->probeCntr   = 4;
  79    }
  80
  81}
  82
  83
  84/*
  85 * The same code handles incoming Open Connection Request,
  86 * Open Request + Ack, Open Connection Ack, Open Connection Denial
  87 *
  88 * We could be in four different states, LISTEN, OPENWAIT, ESTABLISHED,
  89 * OPEN.
  90 */
  91
  92/*
  93 *
  94 * Ok, there are 16 combinations.  8 are do-nothings, 2 have to be
  95 * special cased (Open Deny and Req+Ack on Open session)
  96 *
  97 * Build a table of actions:
  98 *    Ignore?
  99 *    What to match on (local socket, whole address, DestCID, SrcCID)
 100 *    What to send (Ack or Req+Ack)
 101 *    Next State (both the ccb state and the open state)
 102 */
 103
 104/*
 105 *
 106 */
 107typedef struct {
 108    u_char match;               /* Characteristics that have to match 
 109                                 * (Bit-Mapped, see below) */
 110    char action;                /* What to do if CCB matches */
 111    char send;                  /* What to send in response 
 112                                 * (Bit mapped, same as sendCtl field of 
 113                                 * CCB) */
 114    char openState;             /* Next Open state */
 115    char state;                 /* Next ccb state. */
 116    char pad;                   /* Too bad we need this to make structure 
 117                                 * even size */
 118} TBL, *TBLPtr;
 119
 120#define M_LSOC          0x01    /* bit  0 - Match on local socket */
 121#define M_ADDR          0x02    /* bit  1 - Match on whole address */
 122#define M_DCID          0x04    /* bit  2 - Match on DestCID */
 123#define M_SCID          0x08    /* bit  3 - Match SrcCID */
 124#define M_DCIDZERO      0x10    /* bit  4 - Dest CID must be 0 */
 125#define M_SCIDZERO      0x20    /* bit  5 - Src CID must be 0 */
 126#define M_FILTER        0x40    /* bit  6 - Match address filter */
 127#define M_IGNORE        0x80    /* bit  7 - Ignore */
 128
 129#define A_COMPLETE      0x01    /* Complete open parameter block */
 130#define A_SAVEPARMS     0x02    /* Save connection parameters */
 131#define A_OREQACKOPEN   0x04    /* special case for open Req+Ack on 
 132                                 * OPEN session */
 133#define A_GLEAN         0x08    /* We'll be talking back to this guy */
 134#define A_DENY          0x10    /* We've been denied! */
 135
 136
 137/*
 138 * So here's our table
 139 */
 140
 141static TBL tbl[16] = {
 142
 143/*
 144 * For Open Request ($81)
 145 *
 146 *      LISTENING
 147 *              Match on destination socket
 148 *              Match on address filter
 149 *              Dest CID must be 0
 150 *              Glean connection
 151 *              Save Open Connection parameters
 152 *              Send OREQACK
 153 *              Change state to ESTABLISHED
 154 */
 155        {       M_LSOC + M_DCIDZERO + M_FILTER,
 156                A_SAVEPARMS + A_GLEAN,
 157                B_CTL_OREQACK,
 158                O_STATE_ESTABLISHED,
 159                sOpening,
 160                0
 161        },
 162
 163/*
 164 *
 165 *      OPENWAIT
 166 *              Match on Remote Address & destination socket
 167 *              Dest CID must be 0
 168 *              Save Open Connection parameters
 169 *              Send Ack
 170 *              Change state to ESTABLISHED
 171 */
 172        {       M_LSOC + M_ADDR + M_DCIDZERO,
 173                A_SAVEPARMS + A_GLEAN,
 174                B_CTL_OACK,
 175                O_STATE_ESTABLISHED,
 176                sOpening,
 177                0
 178        },
 179/*
 180 *
 181 *      ESTABLISHED
 182 *              Match on Remote Address & SrcCID
 183 *              Dest CID must be 0
 184 *              Send Req + Ack
 185 */
 186        {       M_ADDR + M_SCID + M_DCIDZERO, 
 187                A_GLEAN, 
 188                B_CTL_OACK, 
 189                O_STATE_ESTABLISHED,
 190                sOpening,
 191                0
 192        },
 193/*
 194 *      OPEN
 195 *              Ignore
 196 */
 197        {       M_IGNORE, 
 198                0, 
 199                0, 
 200                0,
 201                0,
 202                0
 203        },
 204
 205/*
 206 *
 207 * For Open Ack ($82)
 208 *
 209 *      LISTENING
 210 *              Ignore
 211 */
 212        {       M_IGNORE, 
 213                0, 
 214                0, 
 215                0,
 216                0,
 217                0
 218        },
 219/*
 220 *
 221 *      OPENWAIT
 222 *              Ignore
 223 */
 224        {       M_IGNORE, 
 225                0, 
 226                0, 
 227                0, 
 228                0, 
 229                0
 230        },
 231/*
 232 *
 233 *      ESTABLISHED
 234 *              Match on SrcCID & DestCID & Address & Local Socket
 235 *              Complete Listen or Connect PB
 236 *              OPEN
 237 */
 238        {       M_ADDR + M_DCID + M_SCID + M_LSOC, 
 239                A_COMPLETE + A_GLEAN, 
 240                0, 
 241                O_STATE_OPEN,
 242                sOpen,
 243                0
 244        },
 245/*
 246 *
 247 *      OPEN
 248 *              Ignore
 249*/
 250        {       M_IGNORE, 
 251                0, 
 252                0, 
 253                0, 
 254                0, 
 255                0
 256        },
 257
 258/*
 259 *
 260 * For Open Request + Ack ($83)
 261 *
 262 *      LISTENING
 263 *              Ignore
 264*/
 265        {       M_IGNORE, 
 266                0, 
 267                0, 
 268                0, 
 269                0, 
 270                0
 271        },
 272/*
 273 *
 274 *      OPENWAIT
 275 *              Match on DestCID & socket
 276 *                      Do not test remote address -- our open req could have
 277 *                      been passed to another address by a connection server
 278 *              Save Open Connection parameters
 279 *              Complete Connect parameter block
 280 *              Send Ack
 281 *              OPEN
 282 */
 283        {       M_DCID + M_LSOC,
 284                A_COMPLETE + A_SAVEPARMS + A_GLEAN,
 285                B_CTL_OACK,
 286                O_STATE_OPEN,
 287                sOpen,
 288                0
 289        },
 290/*
 291 *
 292 *      ESTABLISHED
 293 *              Ignore
 294 */
 295        {       M_IGNORE, 
 296                0, 
 297                0, 
 298                0, 
 299                0, 
 300                0
 301        },
 302/*
 303 *
 304 *      OPEN
 305 *              Match on Remote Address & SrcCID & DestCID & Local Socket
 306 *              If we've never gotten any data
 307 *              Send Ack & Retransmit
 308 */
 309        {       M_ADDR + M_DCID + M_SCID + M_LSOC,
 310                A_OREQACKOPEN + A_GLEAN,
 311                B_CTL_OACK,
 312                O_STATE_OPEN,
 313                sOpen,
 314                0
 315        },
 316
 317/*
 318 *
 319 *
 320 * For Open Deny ($84)
 321 *
 322 *      LISTENING
 323 *              Ignore
 324 */
 325        {       M_IGNORE, 
 326                0, 
 327                0, 
 328                0, 
 329                0, 
 330                0
 331        },
 332/*
 333 *
 334 *      OPENWAIT
 335 *              Match on DestCID & Address
 336 *              Source CID must be 0
 337 *              Complete with error
 338 */
 339        {       M_SCIDZERO + M_DCID + M_ADDR, 
 340                A_DENY,
 341                0, 
 342                O_STATE_NOTHING,
 343                sClosed,
 344                0
 345        },
 346/*
 347 *
 348 *      ESTABLISHED
 349 *              Ignore
 350 */
 351        {       M_IGNORE, 
 352                0, 
 353                0, 
 354                0, 
 355                0, 
 356                0
 357        },      /* %%% No we probably don't want to ignore in this case */
 358/*
 359 *
 360 *    OPEN
 361 *       Ignore
 362 */
 363        {       M_IGNORE, 
 364                0, 
 365                0, 
 366                0, 
 367                0, 
 368                0
 369        }
 370};
 371
 372extern at_ifaddr_t *ifID_table[];
 373
 374/*
 375 * Used to search down queue of sessions for a session waiting for an
 376 * open request.
 377 */
 378typedef struct {
 379   AddrUnion    addr;
 380   word         dstCID;
 381   word         srcCID;
 382   byte         socket;
 383   byte         descriptor;
 384   byte         idx;            /* Index into state tables */
 385   TBLPtr       t;              /* Ptr to entry in table above */
 386} MATCH, *MATCHPtr;
 387
 388/*
 389 * MatchStream
 390 *
 391 * Called by Rx connection to find which stream (if any) should get this open
 392 * request/ack/req+ack/deny packet.
 393 *
 394 */
 395
 396static boolean
 397MatchStream(sp, m)              /* (CCBPtr sp, MATCHPtr m) */
 398    CCBPtr sp;
 399    MATCHPtr m;
 400{
 401        unsigned char match;
 402        struct adspcmd  *opb;
 403    
 404        if (sp->openState < O_STATE_LISTEN ||
 405            sp->openState > O_STATE_OPEN)
 406            return 0;
 407
 408
 409        m->t = &tbl[sp->openState - O_STATE_LISTEN + m->idx];
 410
 411        match = m->t->match;    /* Get match criteria */
 412
 413        if (match & M_IGNORE)   /* Ignore this combination */
 414            return 0;
 415
 416        if (match & M_LSOC) {   /* Match on Local socket */
 417            if (sp->localSocket != m->socket)
 418                return 0;
 419        }
 420
 421        if (match & M_ADDR) {   /* Match on Address */
 422            AddrUnion   addr;
 423            addr = m->addr;     /* Make local copy for efficiency */
 424            if (sp->remoteAddress.a.node != addr.a.node)
 425                return 0;
 426            if (sp->remoteAddress.a.socket != addr.a.socket)
 427                return 0;
 428            if (sp->remoteAddress.a.net && addr.a.net &&
 429                (sp->remoteAddress.a.net != addr.a.net))
 430                return 0;
 431                        
 432            /*
 433             * Handle special case to reject self-sent open request
 434             */
 435            if ((m->srcCID == sp->locCID) && 
 436                (addr.a.node == ifID_home->ifThisNode.s_node) &&
 437                /* *** was (addr.a.node == ddpcfg.node_addr.node) && *** */
 438                ((addr.a.net == 0) || 
 439                 (ifID_home->ifThisNode.s_net == 0) || 
 440                 (ifID_home->ifThisNode.s_net == addr.a.net)) )
 441              /* *** was 
 442                (NET_VALUE(ddpcfg.node_addr.net) == 0) || 
 443                (NET_VALUE(ddpcfg.node_addr.net) == NET_VALUE(addr.a.net))) )
 444                 *** */
 445                                /* CID's match, and */
 446                                /* If nodeID matches, and */
 447                                /* network matches, */
 448                return 0;       /* then came from us! */
 449        }
 450        
 451        if (match & M_DCID) {   /* Match on DestCID */
 452            if (sp->locCID != m->dstCID)
 453                return 0;
 454        }
 455        
 456        if (match & M_SCID) {   /* Match on SourceCID */
 457            if (sp->remCID != m->srcCID)
 458                return 0;
 459        }
 460        
 461        if (match & M_DCIDZERO) { /* Destination CID must be 0 */
 462            if (m->dstCID != 0)
 463                return 0;
 464        }
 465        
 466        if (match & M_SCIDZERO) /* Source CID must be 0 */
 467        {
 468            if (m->srcCID != 0)
 469                return 0;
 470        }
 471        
 472        if (match & M_FILTER) { /* Check address filter? */
 473            if ((opb = sp->opb)) /* There should be a param block... */
 474            {
 475                AddrUnion       addr;
 476                addr = m->addr; /* Make local copy for efficiency */
 477                if ((opb->u.openParams.filterAddress.net && 
 478                     addr.a.net &&
 479                     opb->u.openParams.filterAddress.net != addr.a.net) ||
 480                    (opb->u.openParams.filterAddress.node != 0 &&
 481                     opb->u.openParams.filterAddress.node != addr.a.node)||
 482                    (opb->u.openParams.filterAddress.socket != 0 &&
 483                     opb->u.openParams.filterAddress.socket != addr.a.socket))
 484                    return 0;
 485            }
 486        }
 487        
 488        return 1;
 489}
 490
 491/*
 492 * MatchListener
 493 *
 494 * Called by rx connection to see which connection listener (if any) should
 495 * get this incoming open connection request.
 496 *
 497 */
 498
 499static boolean MatchListener(sp, m) /* (CCBPtr sp, MATCHPtr m) */
 500    CCBPtr sp;
 501    MATCHPtr m;
 502{
 503
 504    if ((sp->state == (word)sListening) && /* This CCB is a listener */
 505        (sp->localSocket == m->socket)) /* on the right socket */
 506        return 1;
 507    
 508    return 0;
 509}
 510
 511/*
 512 * RXConnection
 513 *
 514 * We just received one of the 4 Open Connection packets
 515 * Interrupts are masked OFF at this point
 516 *
 517 * INPUTS:
 518 *      spPtr   Place to put ptr to stream (if we found one -- not 
 519 *                                              for listeners)
 520 *      f       Pointer to ADSP header for packet, data follows behind it
 521 *      len     # of byte in ADSP header + data
 522 *      addr    Who sent the packet
 523 *      dsoc    Where they sent it to
 524 *
 525 * OUTPUTS:
 526 *    Returns 1 if packet was ignored
 527 */
 528static int RXConnection(gref, spPtr, f, len, addr, dsoc) 
 529    /* (CCBPtr *spPtr, ADSP_FRAMEPtr f, word len, AddrUnion addr, byte dsoc) */
 530    gref_t *gref;                       /* READ queue */
 531    CCBPtr *spPtr;
 532    ADSP_FRAMEPtr f;
 533    int len;
 534    AddrUnion addr;
 535    unsigned char dsoc;
 536{
 537    CCBPtr sp;
 538    ADSP_OPEN_DATAPtr op;
 539    struct adspcmd *pb;
 540    MATCH m;
 541    gbuf_t *mp;
 542    ADSP_FRAMEPtr adspp;
 543    ADSP_OPEN_DATAPtr adspop;
 544    int s;
 545
 546    op = (ADSP_OPEN_DATAPtr)&f->data[0]; /* Point to Open-Connection parms */
 547    len -= ADSP_FRAME_LEN;
 548    
 549    if (len < (sizeof(ADSP_OPEN_DATA))) /* Packet too small */
 550        return 1;
 551
 552
 553    if (UAS_VALUE(op->version) != netw(0x0100)) { /* Check version num (on even-byte) */
 554        /*
 555         * The open request has been denied.  Try to send him a denial.  
 556         */
 557
 558        mp = gbuf_alloc(AT_WR_OFFSET + DDPL_FRAME_LEN + ADSP_FRAME_LEN + ADSP_OPEN_FRAME_LEN,
 559                    PRI_LO);
 560        gbuf_rinc(mp,AT_WR_OFFSET);
 561        gbuf_wset(mp,DDPL_FRAME_LEN);
 562        adspp = (ADSP_FRAMEPtr)gbuf_wptr(mp);
 563        gbuf_winc(mp,ADSP_FRAME_LEN);
 564        bzero((caddr_t) gbuf_rptr(mp),DDPL_FRAME_LEN + ADSP_FRAME_LEN + 
 565              ADSP_OPEN_FRAME_LEN);
 566        adspp->descriptor = ADSP_CONTROL_BIT | ADSP_CTL_ODENY;
 567        adspop = (ADSP_OPEN_DATAPtr)gbuf_wptr(mp);
 568        gbuf_winc(mp,ADSP_OPEN_FRAME_LEN);
 569        UAS_UAS(adspop->dstCID, f->CID);
 570        UAS_ASSIGN(adspop->version, 0x100);
 571        adsp_sendddp(0, mp, DDPL_FRAME_LEN + ADSP_FRAME_LEN + 
 572                   ADSP_OPEN_FRAME_LEN, &addr, DDP_ADSP);
 573
 574        return 0;
 575    }
 576    m.addr = addr;
 577    m.socket = dsoc;
 578    m.descriptor = f->descriptor;
 579    m.srcCID = UAS_VALUE(f->CID);
 580    m.dstCID = UAS_VALUE(op->dstCID);   /* On even-byte boundry */
 581    m.idx = ((f->descriptor & ADSP_CONTROL_MASK) - 1) * 4;
 582                                          
 583    /*
 584     * See if we can find a stream that knows what to do with this packet
 585     */
 586    if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, (ProcPtr)MatchStream)) == 0)
 587    {
 588        struct adspcmd *p;
 589        struct adspcmd *n;
 590        /*
 591         * No match, so look for connection listeners if this is an 
 592         * open request
 593         */
 594        if ((f->descriptor & ADSP_CONTROL_MASK) != (byte)ADSP_CTL_OREQ)
 595            return 1;
 596
 597        if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, 
 598                                  (ProcPtr)MatchListener)) == 0)
 599            return 1;
 600
 601        ATDISABLE(s, sp->lock);
 602        p = (struct adspcmd *)&sp->opb;
 603        while (n = (struct adspcmd *)p->qLink) /* Hunt down list of listens */
 604        {
 605            /* Check address filter */
 606            if (((n->u.openParams.filterAddress.net == 0) ||
 607                 (addr.a.net == 0) ||
 608                 (n->u.openParams.filterAddress.net == addr.a.net)) &&
 609                
 610                ((n->u.openParams.filterAddress.node == 0) || 
 611                 (n->u.openParams.filterAddress.node == addr.a.node)) &&
 612                
 613                ((n->u.openParams.filterAddress.socket == 0) || 
 614                 (n->u.openParams.filterAddress.socket == addr.a.socket))) {
 615                p->qLink = n->qLink; /* Unlink this param block */
 616                n->u.openParams.remoteCID = m.srcCID;
 617                *((AddrUnionPtr)&n->u.openParams.remoteAddress) = addr;
 618                n->u.openParams.sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq));
 619                n->u.openParams.sendWindow = netw(UAS_VALUE(f->pktRecvWdw));
 620                n->u.openParams.attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq));
 621                n->ioResult = 0;
 622                ATENABLE(s, sp->lock);
 623                completepb(sp, n); /* complete copy of request */
 624                                /* complete(n, 0); */
 625                return 0;
 626            }                   /* found CLListen */
 627                        
 628            p = n;              /* down the list we go... */
 629                        
 630        }                       /* while */
 631                
 632        ATENABLE(s, sp->lock);
 633        return 1;
 634    }
 635        
 636    *spPtr = sp;                /* Save ptr to stream we just found */
 637        
 638        ATDISABLE(s, sp->lock);
 639    sp->openState = m.t->openState; /* Move to next state (may be same) */
 640    sp->state = m.t->state;     /* Move to next state (may be same) */
 641
 642    if (m.t->action & A_SAVEPARMS) { /* Need to Save open-conn parms */
 643        sp->firstRtmtSeq = sp->sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq));
 644        sp->sendWdwSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)) + netw(UAS_VALUE(f->pktRecvWdw)) - 1;
 645        sp->attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); /* on even boundry */
 646
 647                
 648        sp->remCID = UAS_VALUE(f->CID); /* Save Source CID as RemCID */
 649        UAS_UAS(sp->of.dstCID, f->CID); /* Save CID in open ctl packet */
 650                
 651        sp->remoteAddress = addr; /* Save his address */
 652
 653    }
 654        ATENABLE(s, sp->lock);
 655
 656    if (m.t->action & A_DENY) { /* We've been denied ! */
 657        DoClose(sp, errOpenDenied, -1);
 658    }
 659
 660    if (m.t->action & A_OREQACKOPEN) { 
 661                                /* Special case for OREQACK */
 662                                /* on an open session */
 663        RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
 664        sp->sendSeq = sp->firstRtmtSeq;
 665        sp->pktSendCnt  = 0;
 666        sp->waitingAck  = 0;
 667        sp->callSend = 1;
 668    }
 669
 670    if (m.t->send) {            /* Need to send a response */
 671        sp->sendCtl |= m.t->send;
 672        sp->callSend = 1;
 673    }
 674
 675    if (m.t->action & A_COMPLETE) { /* Need to complete open param blk */
 676        RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer);
 677                        
 678        if (pb = sp->opb) {
 679            sp->opb = 0;
 680            pb->u.openParams.localCID = sp->locCID;
 681            pb->u.openParams.remoteCID = sp->remCID;
 682            pb->u.openParams.remoteAddress = 
 683                *((at_inet_t *)&sp->remoteAddress);
 684            pb->u.openParams.sendSeq = sp->sendSeq;
 685            pb->u.openParams.sendWindow = sp->sendWdwSeq - sp->sendSeq;
 686            pb->u.openParams.attnSendSeq = sp->attnSendSeq;
 687            pb->ioResult = 0;
 688            completepb(sp, pb); /* complete(pb, 0); */
 689            return 0;
 690        }
 691                                /* Start probe timer */
 692        InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, 
 693                        sp->probeInterval);
 694    }
 695    return 0;
 696}
 697
 698/*
 699 * ADSPPacket
 700 *
 701 * When a packet is received by the protocol stack with DDP type equal
 702 * to ADSP, then execution comes here
 703 *
 704 * DS is set to ATALK's DGROUP
 705 *
 706 * This routine, or one of its children MUST call glean packet
 707 *
 708 * INPUTS:
 709 *    Pointer to DDP header 
 710 * OUTPUTS:
 711 *    none
 712 *
 713 * Note that the incoming message block (mp) is usually discarded, either
 714 * by the "ignored" path, or via the "checksend" path.  The only case
 715 * where the message is NOT freed is via the RxData case in the
 716 * non control packet switch.  I zero mp after the RxData case succeeds
 717 * so that mp will not be freed.
 718 */
 719int adspPacket(gref, mp) 
 720    /* (bytePtr data, word len, AddrUnion a, byte dsoc) */
 721    gref_t *gref;
 722    gbuf_t *mp;
 723{
 724    unsigned char *bp;
 725    int len;
 726    AddrUnion a;
 727    int dsoc;
 728    int s;
 729    register DDPX_FRAME *ddp;   /* DDP frame pointer */
 730    register ADSP_FRAMEPtr f;   /* Frame */
 731    CCBPtr sp;
 732
 733    sp = 0;                     /* No stream */
 734    bp = (unsigned char *)gbuf_rptr(mp);
 735    ddp = (DDPX_FRAME *)bp;
 736    if (ddp->ddpx_type != DDP_ADSP)
 737        return -1;
 738    f = (ADSP_FRAMEPtr)(bp + DDPL_FRAME_LEN);
 739
 740    len = UAS_VALUE(ddp->ddpx_length) & 0x3ff; /* (ten bits of length) */
 741    len -= DDPL_FRAME_LEN;
 742    if (len < (sizeof(ADSP_FRAME) - 1)) /* Packet too small */
 743        return -1;              /* mark the failure */
 744
 745    a.a.net = NET_VALUE(ddp->ddpx_snet);
 746    a.a.node = ddp->ddpx_snode;
 747    a.a.socket = ddp->ddpx_source;
 748
 749    dsoc = ddp->ddpx_dest;
 750
 751    if (sp = (CCBPtr)FindSender(f, a))
 752        GleanSession(sp);
 753
 754    if (f->descriptor & ADSP_ATTENTION_BIT) { /* ATTN packet */
 755        if (sp && RXAttention(sp, mp, f, len)) 
 756            goto ignore;
 757        else
 758            mp = 0;             /* attention data is being held */
 759    }                           /* ATTENTION BIT */
 760
 761    else if (f->descriptor & ADSP_CONTROL_BIT) { /* Control packet */
 762        switch (f->descriptor & ADSP_CONTROL_MASK) {
 763        case ADSP_CTL_PROBE:    /* Probe or acknowledgement */
 764            if (sp)
 765                CheckRecvSeq(sp, f);
 766            break;
 767
 768        case ADSP_CTL_OREQ:     /* Open Connection Request */
 769        case ADSP_CTL_OREQACK:  /* Open Request and acknowledgement */
 770        case ADSP_CTL_OACK:     /* Open Request acknowledgment */
 771        case ADSP_CTL_ODENY:    /* Open Request denial */
 772            if (RXConnection(gref, &sp, f, len, a, dsoc))
 773                goto ignore;
 774            break;
 775                        
 776        case ADSP_CTL_CLOSE:    /* Close connection advice */
 777            if (sp) {
 778                /* This pkt may also ack some data we sent */
 779                CheckRecvSeq(sp, f); 
 780                RxClose(sp);
 781                sp = 0;
 782            } else
 783                goto ignore;
 784            break;
 785
 786        case ADSP_CTL_FRESET:   /* Forward Reset */
 787                                /* May I rot in hell for the code below... */
 788            if (sp && (CheckRecvSeq(sp, f), RXFReset(sp, f)))
 789                goto ignore;
 790            break;
 791                        
 792        case ADSP_CTL_FRESET_ACK: /* Forward Reset Acknowledgement */
 793            if (sp && (CheckRecvSeq(sp, f), RXFResetAck(sp, f)))
 794                goto ignore;
 795            break;
 796
 797        case ADSP_CTL_RETRANSMIT: /* Retransmit advice */
 798            if (sp) {
 799                /* This pkt may also ack some data we sent */
 800                CheckRecvSeq(sp, f); 
 801                RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
 802                ATDISABLE(s, sp->lock);
 803                sp->sendSeq = sp->firstRtmtSeq;
 804                sp->pktSendCnt = 0;
 805                sp->waitingAck = 0;
 806                sp->callSend = 1;
 807                ATENABLE(s, sp->lock);
 808            } else
 809                goto ignore;
 810            break;
 811                        
 812        default:
 813            goto ignore;
 814        }                       /* switch */
 815    }                           /* Control packet */
 816
 817    else {                      /* Data Packet */
 818        if ((sp == 0) || RXData(sp, mp, f, len))
 819            goto ignore;
 820        else
 821            mp = 0;             /* RXData used up the data, DONT free it! */
 822    }                           /* Data Packet */
 823
 824    if (mp)
 825        gbuf_freem(mp);
 826
 827checksend:                      /* incoming data was not ignored */
 828    if (sp && sp->callSend)     /* If we have a stream & we need to send */
 829        CheckSend(sp);
 830    
 831    return 0;
 832        
 833ignore:
 834    gbuf_freem(mp);
 835    return 0;
 836}
 837
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.