📄 ni_pppoe.c
字号:
/************************************************************************/
/* */
/* 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 + -