ppp.c

来自「PPP协议C语言源代码」· C语言 代码 · 共 2,014 行 · 第 1/5 页

C
2,014
字号
                return 0;
           /* If in/out failed or down done */
            else if (prevstate == -1 || IS_MODEM_DIALDOWN(netp)) {
                if (IS_MODEM_DIALOUT(netp)) {
                    PPPSIG_DIALOUT_DOWN(netno);
                }
                else if (IS_MODEM_DIALIN(netp)) {
                    PPPSIG_DIALIN_DOWN(netno);
                }
                else if (prevstate == -1) {
                    PPPSIG_DIALDOWN_DOWN(netno);
                }
                else {
                    PPPSIG_DIALDOWN_UP(netno);
                }
                WAITNOMORE(SIG_WN(netno));
                MODEM_DIALIN(netno);
                PPPSIG_PPP_DOWN(netno);
                return -1;
            }
           /* If success and active */
            else if (IS_MODEM_DIALOUT(netp)) {
                PPPSIG_DIALOUT_UP(netno);
                pppForceUp(netno);
            }
            else {
                PPPSIG_DIALIN_UP(netno);
#if IDLE_TOUT
               /* If success and passive */
                netp->hw.idle_time = TimeMS();
#endif
            }
        }
#if IDLE_TOUT
       /* If remote dialed in without starting PPP, hangup after timeout. */
        else if ((netconf[netp->confix].flags & DIAL) && IS_MODEM_DIALIN(netp)) {
            if (((TimeMS()-netp->hw.idle_time)>>10) > IDLE_TOUT)
                goto term;
        }
#endif
        else
            return -1;
        return 0;
#else
        return -1;
#endif
    }

   /* Check for a timeout. */
    prevstate = netp->state;
    ul2 = TOUTMS;
#if TOUT_GROW
    ul2 >>= (netp->hw.opt7/2);
#endif
    if ((ul1 - netp->hw.timems) > ul2) {
        if (netp->state == PPPclsng) {
            if (netp->hw.opt7 <= 0) {
#if NTRACE >= 3
                Nprintf("PPP: Terminate counter expired\n");
                Nprintf("PPP: Link closed\n");
#endif
                netp->state = PPPclsd;
                pppDQ(netno);
                PPPSIG_LCP_DOWN(netno);
#if DIALD
                if ((netconf[netp->confix].flags & DIAL) == 0)
#endif
                {
                    PPPSIG_PPP_DOWN(netno);
                }

                pppForceDown(netno);
                return -1;
            }
        }
        else if (netp->hw.opt7 <= 0) {
#if NTRACE >= 3
            Nprintf("PPP: Restart counter expired\n");
#endif
term:
            pppForceDown(netno);
        }
        else if ((netp->state & LCPopen) != LCPopen)
            netp->state &= ~(LCPtxREQ | LCPrxACK);
        else if (netp->hw.opt4 & AUTHhini)
            netp->hw.opt4 &= ~AUTHwait;
        else if ((netp->state & IPCPopen) != IPCPopen)
            netp->state &= ~(IPCPtxREQ | IPCPrxACK);

       /* If we can't get a buffer, make timeouts work normally */
        if ((mess = Ngetbuf()) == 0) {
            netp->state = prevstate;
            return 0;
        }
        netp->hw.timems = ul1;
        mess->netno = netno;
        pppNegotiate(mess);
        mess->id = bALLOC;
        Nrelbuf(mess);
    }

    return 0;   /* Link/modem working */
}


/*
** * * * * * *
** writE()  External/Internal function to write out a frame
**
** static int writE(int conno, MESS *mess);
**
** PARAMETERS:
**  (in) conno                 A yfnet connection number
**  (in/out) mess              A pointer to a buffer to write out
**
** RETURNS:
** -1                          Cannot queue packet or driver error
**  0                          Frame taken care of (queued)
**  1                          Frame sent immediately
**
** DESCRIPTION:
**  This function will frame and write a buffer.
**
** * * * * * *
*/
static int writE(int conno, MESS *mess)
{
    int i1, netno;
    unsigned short us1, protoc;
    unsigned char *cp;
    struct NET *netp;
#if VJ
    MESS *mp2;
#endif

    netno = mess->netno;
    netp = &nets[netno];

    (void) conno;

   /*
    ** If PPP is not Open:
    **      Queue datagram (if configured)
    **      Force link open
    */
    if (netp->state != PPPopen) {
#if DBUFFER
        if (!QUEUE_FULL(netp, future) && netp->hw.opt8 < DBUFFER_SZ) {
            netp->hw.opt8++;
            mess->conno = conno;
            QUEUE_IN(netp, future, mess);
#if NTRACE >= 5
            Nprintf("PPP: Datagram queued for con %d\n", conno);
#endif
        }
        else {
#if NTRACE
            Nprintf("PPP: Queue full, datagram dropped on con %d!\n", conno);
#endif
            mess->offset = boTXDONE;    /* "Send" the packet */
        }
#endif
        pppForceUp(netno);
        YIELD();
#if MP
       /* Find the next companion link to open for Multilink */
        if (netp->hw.opt5 & MPmrru)
            while (++netno < NNETS)
                if (nets[netno].netstat &&
                    nets[netno].hw.opt5 & MPmrru &&
                    strcmp(netconf[netp->confix].pname,
                           netconf[nets[netno].confix].pname) == 0)
                {
                    netconf[nets[netno].confix].Iaddr.l =
                            netconf[netp->confix].Iaddr.l;
                    nets[netno].haddr.l = netp->haddr.l;
                    nets[netno].raddr.l = netp->raddr.l;
                    pppForceUp(netno);
                    YIELD();
                }
#endif
#if DBUFFER
        if (mess->offset == boTXDONE)   /* Sent immediately */
            return 1;
        return 0;                       /* Queued in--not sent yet */
#else
        mess->offset = boTXDONE;
        return 1;
#endif
    }


   /*
    ** Here is the normal link layer write
    **      Update idle link time (if configured)
    **      Compress TCP/IP header (if configured)
    **      Create the PPP frame
    **          Add protocol (compressed or uncompressed)
    **          Encapsulate in Multilink frame (if configured)
    **          Add address/control for AHDLC (if not compressed)
    **          Create checksum and append it to the frame
    **      Transmit frame
    */
#if IDLE_TOUT
    netp->hw.idle_time = TimeMS();
#endif

   /* Call TCP/IP header compression if wanted. */
    if ((protoc = PH(mess)->protocol) == NC2(0x0800)) {
        protoc = NC2(PROTip);
#if VJ
        if (TXslots[netno]) {
            protoc = vjWrite(mess, &mp2);
            if (protoc == NC2(PROTcomp))
                mess = mp2;
        }
#endif
    }


   /* Point to PPP information field */
    cp = (unsigned char *)mess + MESSH_SZ + LHDRSZ;

    PH(mess)->MACtype = 0;  /* No compression (yet) for WRAP driver */


   /* Store protocol code */
    *--cp = ((char *)&protoc)[1];
#if (COMPRESSION & 1) == 0
    *--cp = *((char *)&protoc);
#else
    if (netp->hw.remopts & COMPpcmp && *(char *)&protoc == 0) {
        *(cp - 1) = 0;
        PH(mess)->MACtype |= 1; /* For WRAP driver */
    }
    else
        *--cp = *((char *)&protoc);
#endif


#if MP
   /* For multilink protocol, store MP header and get transmit link number */
    if (netp->hw.opt5 & MPmrru) {
        mess->netno = mpWrite(netno, &cp);
        netp = &nets[mess->netno];
#if COMPRESSION & 1
        if (netp->hw.remopts & COMPpcmp)
            PH(mess)->MACtype |= 1;
#endif
    }
#endif


   /* Create async framing */
    if (netp->ifType == 23) {
#if COMPRESSION & 1
        if (netp->hw.remopts & COMPacmp)
            PH(mess)->MACtype |= 2; /* For WRAP driver */
        else
#endif
        {
            *--cp = 0x03;   /* Control */
            *--cp = 0xff;   /* Address */
        }

       /* Set driver offset */
        PH(mess)->poffset = cp - (unsigned char *)mess;
        i1 = mess->mlen - PH(mess)->poffset;

       /* Calculate and append AHDLC checksum */
        us1 = 0xffff;
        while (i1--)
            us1 = (us1 >> 8) ^ fcstab[(us1 ^ *cp++) & 0xff];
        us1 ^= 0xffff;
        *cp++ = us1;
        *cp = us1 >> 8;
    }

#ifdef MIB2
    netp->ifOutOctets += mess->mlen - PH(mess)->poffset + 2;
    netp->ifOutUcastPkts++;
#endif

    us1 = mess->id;

   /* Write out the packet by calling the driver */
    i1 = netp->protoc[1]->writE(netno, mess);
    if (i1 != 0 || us1 <= bWACK)
        return i1;

    WAITFOR(mess->offset == boTXDONE, SIG_WN(netno), netp->tout, i1);
    return 1;
}


/*
** * * * * * *
** comec()  Character input interrupt routine
**
** static void comec(int cc, struct NET *netp);
**
** PARAMETERS:
**  (in) cc                     A character to input
**  (in/out) netp               A pointer to a network structure
**
** RETURNS (not implemented):
**  0                           Character processed (do nothing)
**  1                           Enable host driver transmit interrupt
** -1                           Transmit XOFF
**
** DESCRIPTION:
**  This function takes in a HDLC framed character and maps it to a
**  data entity in the in buffer.
**
** * * * * * *
*/
static void comec(int cc, struct NET *netp)
{
    MESS *mess;

   /* If first octet in */
    if (netp->hw.bufin == 0) {
       /* FLAG (0x7e) should always begin and end a PPP HDLC frame */
        if (cc != FLAG && netp->hw.lastin != FLAG)
            return;

       /* Make buffer to put data from network */
        if ((netp->bufbas = NgetbufIR()) == 0)
            return;
       /* netp->hw.bufin = (char *)&PH(netp->bufbas)->flag; */
        netp->hw.bufin = (char *)netp->bufbas + MESSH_SZ + HOFF;
        netp->hw.buflim = (char *)netp->bufbas + MAXBUF;
        mess = netp->bufbas;
        PH(mess)->MACtype = 0;
        PH(mess)->poffset = MESSH_SZ + HOFF + 1;    /* After flag */
        netp->hw.opt3 = 0;              /* Start of frame */
        if (cc == FLAG)                 /* First character should be 0x7e */
            goto lab4;
        *netp->hw.bufin++ = FLAG;       /* lastin was flag so now use it */
    }

    if (netp->hw.lastin == CTL_ESC) {   /* Current character is escaped */
        cc ^= 0x20;                     /* Decode character */
        netp->hw.lastin = 0;
        goto lab3;
    }

    netp->hw.lastin = cc;
    if (cc == CTL_ESC)                  /* Next character is data */
        return;

    if (cc == FLAG) {                   /* End of frame flag found */
        mess = netp->bufbas;
        mess->mlen = netp->hw.bufin - (char *)mess - 2;
        mess->netno = netp->netno;

       /* If message size is less than header, an error must have occured */
        if (mess->mlen <= MESSH_SZ + LHDRSZ) {
           /* Flag must have signaled beginning of frame, not end */
            netp->hw.bufin = (char *)netp->bufbas + MESSH_SZ + HOFF;
            goto lab4;
        }

        if (QUEUE_FULL(netp, arrive))
            NrelbufIR(mess);
        else {
            PH(mess)->poffset += PH(mess)->MACtype;
            QUEUE_IN(netp, arrive, mess);
        }
        WAITNOMORE_IR(SIG_RN(netp->netno));
        netp->hw.bufin = 0;
        return;
    }

lab3:
   /*
    ** Check only the first three characters for addr/ctl and protocol.
    ** If there are any problems, let screen() take care of them.
    */
    if (netp->hw.opt3 < 4) {
        netp->hw.opt3++;

#if COMPRESSION & 1
       /*
        ** If first byte in is not the address and address/control
        ** compression is enabled, make a note of it and go on.  Tell the
        ** portion of code that looks for the protocol field that it is here
        ** (opt3 == 3).
        */
        if (netp->hw.locopts & COMPacmp &&
            cc != 0xff &&
            netp->hw.opt3 == 1)
        {
            PH(netp->bufbas)->MACtype |= 2; /* Addr/Cntl field compressed */
            netp->hw.bufin += 2;            /* Skip reading them */
            netp->hw.opt3 = 3;
        }

       /*
        ** If the third byte is here and is the lower byte of a protocol
        ** code and protocol compression is enabled, make a note that the
        ** protocol was copmressed.
        */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?