⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ni_pppoe.c

📁 PPPoE协议在Psos中的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************/
/*                                                                      */
/*   MODULE:  ni_ppp.c                                                  */
/*   PRODUCT: pNA+,  OpEN TCP/IP PPP driver                             */
/*   PURPOSE: Network Interface module                                  */
/*   DATE:    28 February, 1996                                         */
/*                                                                      */
/*----------------------------------------------------------------------*/
/*                                                                      */
/*              Copyright 1996, Integrated Systems, Inc.                */
/*                      ALL RIGHTS RESERVED                             */
/*                                                                      */
/*   Permission is hereby granted to licensees of Integrated Systems,   */
/*   Inc. products to use or abstract this computer program for the     */
/*   sole purpose of implementing a product based on Integrated         */
/*   Systems, Inc. products.   No other rights to reproduce, use,       */
/*   or disseminate this computer program, whether in part or in        */
/*   whole, are granted.                                                */
/*                                                                      */
/*   Integrated Systems, Inc. makes no representation or warranties     */
/*   with respect to the performance of this computer program, and      */
/*   specifically disclaims any responsibility for any damages,         */
/*   special or consequential, connected with the use of this program.  */
/*                                                                      */
/************************************************************************/
#include <psos.h>
#include <bsp.h>
#include <pna.h>
#include <bspfuncs.h>
#include <pna_mib.h>
#include "syslog.h"
#include "ni_ppp.h"
#include "pppmisc.h"
#include "fsm.h"
#include "lcp.h"
#include "pppoe.h"

static ULONG ni_init(ULONG (*ap_addr)(), long num, struct ni_funcs *funcs);
static ULONG ni_getpkb(ULONG count, char *adrp);
static ULONG ni_retpkb(char *bufp);
static ULONG ni_send(char *addr, long if_num, char *bufp, ULONG count, ULONG type);
static ULONG ni_ioctl(long if_num, unsigned long cmd, long *arg);
static ULONG ni_poll(long);

PCI pcis[NUM_PPP];              
int nimap[MAXPPPUNITS+1];         /* map from NI number to unit */
struct ppp_pccb PPPpccb[NUM_PPP]; /* Per channel control blocks */
unsigned long psos_up_flag;       /* Flag to show if pSOS is up */
char BroadcastAddr[6]; 

#if OPENTCPIP
unsigned char phyaddress[6] = { 0, 0, 0, 0, 0, 0 } ;
#endif

extern PPPoEConnection Connection;

/************************************************************************/
/* NiPPPoE: PPPoE NI driver switch function                             */
/*                                                                      */
/*     INPUTS: fn_code: NI function code                                */
/*             p: Pointer to parameter block                            */
/*                                                                      */
/*     RETURNS:                                                         */
/*     OUTPUTS:                                                         */
/*     NOTE(S):                                                         */
/*                                                                      */
/************************************************************************/
long NiPPPoE(unsigned long fn_code, union nientry *p)
{
    unsigned long retval;

    switch ((unsigned short)fn_code)
    {
    case NI_INIT:
        retval = ni_init((unsigned long (*)())p->niinit.ap_addr, 
            p->niinit.if_num, p->niinit.funcs);      /* ap_addr:pNA entry to receive packet */
        break;
    case NI_GETPKB:
        retval = ni_getpkb((unsigned long)p->nigetpkb.count,
            (char *)p->nigetpkb.hwa_ptr);
        break;
    case NI_RETPKB:
        ni_retpkb(p->niretpkb.buff_addr);
        retval = 0;
        break;
    case NI_SEND:
        retval = ni_send(Connection.peerEth,/*(char *)p->nisend.hwa_ptr,*/ 
            p->nisend.if_num, p->nisend.buff_addr,
            (unsigned long)p->nisend.count, 
            (unsigned long)p->nisend.type);
        break;
    case NI_BROADCAST:
        retval = ni_send((char *)BroadcastAddr, 
            p->nibrdcast.if_num, p->nibrdcast.buff_addr,
            (unsigned long)p->nibrdcast.count, 
            (unsigned long)p->nibrdcast.type);
        break;	
    case NI_POLL:
        retval = ni_poll(p->nipoll.if_num);
        break;
    case NI_IOCTL:
        retval = ni_ioctl(p->niioctl.if_num,(unsigned long) p->niioctl.cmd, p->niioctl.arg);
        break;
    default:
        retval = (unsigned long) -1;
        break;
    }
    return retval;
}

/************************************************************************/
/* ni_getpkb: Get packet buffer                                         */
/*                                                                      */
/*      INPUTS: count: Length of the packet                             */
/*              adrp: Pointer to destination                            */
/*                                                                      */
/*     RETURNS: Buffer pointer or -1 if none                            */
/*     OUTPUTS:                                                         */
/*     NOTE(S):                                                         */
/*                                                                      */
/************************************************************************/
static unsigned long ni_getpkb(unsigned long count, char *adrp)
{
    syslog(LOG_ERR, "ni_getpkb() called!");
}

/************************************************************************/
/* ni_retpkb: Return the packet buffer                                  */
/*                                                                      */
/*      INPUTS: bufp: Pointer to the buffer                             */
/*                                                                      */
/*     RETURNS: NONE                                                    */
/*     OUTPUTS:                                                         */
/*     NOTE(S):                                                         */
/*                                                                      */
/************************************************************************/
static unsigned long ni_retpkb(char *bufp)
{
    pfree(bufp); /* defined in pppmisc.c */
    return 0;
}

/************************************************************************/
/* ni_poll: Called either by PNAD or probe to send/receive a packet.    */
/*                                                                      */
/*      INPUTS: if_num: interface number                                */
/*                                                                      */
/*     RETURNS: Zero on success else Error                              */
/*     OUTPUTS:                                                         */
/*     NOTE(S):                                                         */
/*              If called from the PNAD, this routine will act exactly  */
/*              as an isr.  So only one character is possibly sent or   */
/*              received.  If otherwise it's called from the probe, it  */
/*              tries to receive one character; but tries to send as    */
/*              many characters as available, since this is the only    */
/*              way those characters are possibly sent.                 */
/************************************************************************/
static unsigned long ni_poll(long if_num)
{
    syslog(LOG_ERR, "ni_poll() called!");
}

/************************************************************************/
/* ni_send: Send a packet. Queue the packet to the transmit task and    */
/*          send a TRANSMIT_EVENT to wake it up to do the sending       */
/*                                                                      */
/*      INPUTS: addr: Pointer to address of destination                 */
/*              bufp: Pointer to the buffer to be sent                  */
/*              count: Length of the packet                             */
/*              type: type of packet (IP or ARP)                        */
/*                                                                      */
/*     RETURNS: Zero on success else Error                              */
/*     OUTPUTS:                                                         */
/*     NOTE(S):                                                         */
/*              Don't need to check size because the upon finish of LCP */
/*              negotiation, pNA's mtu has been adjusted to MIN(ho->mru,*/
/*              BUFSIZE).                                               */
/************************************************************************/
static unsigned long ni_send(char *addr, long if_num, char *bufp, 
unsigned long size, unsigned long type)
{
    int unit = nimap[if_num];
    struct ppp_pccb *ccb = &PPPpccb[unit];
    struct ppp_cfg *ccp = &pppcfgtab[unit];
    PCI *pc = &pcis[unit];
    mblk_t *mb;
    struct mbuf m0, *m = &m0;
    struct ip *ip;
    unsigned short proto,len;
    unsigned long ilev;
    mblk_t *php;

    mb = (mblk_t *) bufp;

    ilev = splx(MAX_ILEV);

    if (ccb->pppstatus != PSUP )
    {
        /* handle the demand dialup case */
        if (ccp->dialmode == PPP_DEMANDDIAL ) {
            unsigned long msg[4];

            /* send output message to the pppd task */
            msg[0] = MSG_OUTPUT;
            msg[1] = unit;
            msg[2] = (long)mb;

            if (q_send(Qid, msg) || ev_send(Tid, PEV_QEVENT))
                ccb->nifuncs.freemsg(mb);

            splx(ilev);
            return(0);
        } else
        {
            ccb->nifuncs.freemsg(mb);
            splx(ilev);
            return(-1);
        }
    }
    splx(ilev);

    proto = htons(PPP_IP);              /* assume IP */

    /*---------------------------------------------------------------*/
    /* Do the VJCOMP before the PPP header stuff.                    */
    /*---------------------------------------------------------------*/
    m->m_len = mb->b_wptr - mb->b_rptr;
    m->m_off = (unsigned char *)mb->b_rptr;
    ip = mtod(m, struct ip *);   /* #define mtod(bp, t) ((t) (bp)->b_rptr) */
    len = ip->ip_len + 2;
    /*----------------------------------------------------------------*/
    /* n.b.-- the `40' below checks that we have a least a min length */
    /* tcp/ip header contiguous in an mbuf.  We don't do `sizeof' on  */
    /* some struct because too many compilers add random padding.     */
    /*----------------------------------------------------------------*/
    if (ip->ip_p == IPPROTO_TCP && m->m_len >= 40 
        && (pc->pci_flags & PCI_FLAGS_VJCOMP))
    {
        register int p;
        p = sl_compress_tcp(m, ip, &pc->pci_comp, (int) pc->pci_flags & PCI_FLAGS_CID);
        if (p == TYPE_UNCOMPRESSED_TCP) proto = htons(PPP_VJC_UNCOMP);
        else if (p == TYPE_COMPRESSED_TCP) proto = htons(PPP_VJC_COMP);
    }

    /*----------------------------------------------------------------*/
    /* update the mblk                                                */
    /*----------------------------------------------------------------*/
    mb->b_rptr = m->m_off;

    /*----------------------------------------------------------------*/
    /* get a pppoe header buffer first                                */
    /*----------------------------------------------------------------*/
    if (!(php = (mblk_t *)DEQUE(&PPPoEHdPool)))
    {
        ccb->mibstat.outdiscards++;
        return(-1);
    }

    /*----------------------------------------------------------------------*/
    /* Put on the PPPoE header.                                             */
    /*----------------------------------------------------------------------*/
    *(u_short *)php->b_wptr = htons( ETH_PPPOE_SESSION );   /* eth type */
    php->b_wptr += 2;
    *php->b_wptr++ = 0x11;        /* ver & type */           
    *php->b_wptr++ = CODE_SESS;   /* code */
    *(u_short *)php->b_wptr = htons( Connection.session );    /* session id */
    php->b_wptr += 2;
    *(u_short *)php->b_wptr = htons( len );      /* length */
    php->b_wptr += 2;
    *(u_short *)php->b_wptr = proto;   /* protocol */
    php->b_wptr += 2;
    
    php->b_cont = mb;       /* put pppheader at the head of the chain */

    /*----------------------------------------------------------------*/
    /* Call the lower layer send routine.                             */
    /*----------------------------------------------------------------*/
    return (output(addr,unit, (u_char *)php, 0));
}

/************************************************************************/
/*  ni_ioctl: IOCTL call                                                */
/*  INPUTS: cmd - MIB II command; arg - ptr to mib_ifreq return struct  */
/* RETURNS: 0 successful; error number otherwise                        */
/* OUTPUTS:                                                             */
/* NOTE(S):                                                             */
/************************************************************************/
static unsigned long ni_ioctl(long if_num, unsigned long cmd, long *arg)
{
    int unit = nimap[if_num];
    struct ppp_pccb *ccb = &PPPpccb[unit];
    struct ppp_cfg *ccp = &pppcfgtab[unit];
    struct mib_ifreq *ifrp;
    struct ifreq *ifr;

    ifr = (struct ifreq *) arg;
    ifrp = (struct mib_ifreq *) arg;

    /*---------------------------------------------------------------------*/
    /* First check if interface administration status is down.  If so, and */
    /* the command is not "Set administration status", just return.        */
    /*---------------------------------------------------------------------*/
    if((ccb->mibstat.ifadminstatus == 2) && (cmd != SIOCSIFADMINSTATUS)
        && (cmd != SIOCGIFADMINSTATUS) && (cmd != SIOCGIFOPERSTATUS)
        && (cmd != SIOCSIFMTU) && (cmd != SIOCSIFADDR) && (cmd != SIOCSIFFLAGS))
    {
        ccb->ppperrno = EMIB;
        ppp_report_error((long) unit, EMIB);
        return ccb->ppperrno;
    };

    switch (cmd)
    {
        /*-----------------------------------------------------------*/
        /* NI ioctls                                                 */
        /*-----------------------------------------------------------*/
    case SIOCSIFMTU:
        ccb->mibstat.mtu = (unsigned long) ifr->ifr_mtu;
        break;
    case SIOCSIFADDR:
        break;          /* nothing to do */
    case SIOCSIFFLAGS:
        /*-----------------------------------------------------------*/
        /* 1) application does an ioctl(iff_down);                   */
        /* 2) SIFDOWN() was called from within PPP                   */
        /* 3) application does an ioctl(iff_up)                      */
        /* 4) SIFUP() called from within PPP:                        */
        /*-----------------------------------------------------------*/
#define IOCSIFDOWN ((ifr->ifr_flags & IFF_UP) == 0)
        if (IOCSIFDOWN) {

⌨️ 快捷键说明

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