📄 ppp.c
字号:
if ( mode & PPP_ESCAPED ) {
ppp_skipped( ppp_p, &head_bp,
"deliberate cancellation" );
ppp_p->InFrame++;
} else if ( mode & PPP_TOSS ) {
free_p(& head_bp );
} else if ( head_bp != NULL ) {
if ( calc_fcs != HDLC_FCS_FINAL ) {
ppp_skipped( ppp_p, &head_bp,
"checksum error" );
ppp_p->InChecksum++;
} else {
/* trim off FCS bytes */
trim_mbuf(&head_bp, len_p(head_bp)-2);
net_route(ifp,&head_bp);
/* Especially on slow machines, serial I/O can be quite
* compute intensive, so release the machine before we
* do the next packet. This will allow this packet to
* go on toward its ultimate destination. [Karn]
*/
kwait(NULL);
}
} else {
ppp_p->InOpenFlag++;
}
/* setup for next buffer */
mode = FALSE;
head_bp = tail_bp = NULL;
calc_fcs = HDLC_FCS_START;
accm = LCP_ACCM_DEFAULT;
/* Use negotiated values if LCP finished */
if (ppp_p->fsm[Lcp].state == fsmOPENED) {
struct lcp_s *lcp_p = ppp_p->fsm[Lcp].pdv;
if (lcp_p->local.work.negotiate & LCP_N_ACCM) {
accm = lcp_p->local.work.accm;
}
}
#ifdef PPP_DEBUG_RAW
if (!(ifp->trace & IF_TRACE_RAW)) {
if ( raw_bp != NULL ) {
free_p(& raw_bp );
raw_bp = NULL;
}
}
#endif
continue;
}
/* We reach here for every byte inside a frame.
* (The order of the following tests is important.)
* Discard spurious control characters.
* Check for escape sequence.
* (Allow escaped escape.)
*/
if ( c < SP_CHAR && (accm & (1L << c)) ) {
continue;
} else if ( mode & PPP_ESCAPED ) {
mode &= ~PPP_ESCAPED;
c ^= HDLC_ESC_COMPL;
} else if ( c == HDLC_ESC_ASYNC ) {
mode |= PPP_ESCAPED;
continue;
}
/* We reach here with a byte for the buffer.
* Make sure there is room for it.
*/
if ( tail_bp == NULL ) {
if ((tail_bp = alloc_mbuf(PPP_ALLOC)) == NULL) {
ppp_skipped( ppp_p, &tail_bp, Nospace );
ppp_p->InMemory++;
mode |= PPP_TOSS;
continue;
}
head_bp = tail_bp;
cp = tail_bp->data;
} else if ( tail_bp->cnt >= tail_bp->size ) {
/* Current mbuf is full */
if ( (tail_bp->next = alloc_mbuf(PPP_ALLOC)) == NULL ) {
/* No memory, drop the whole packet */
ppp_skipped( ppp_p, &head_bp, Nospace );
ppp_p->InMemory++;
head_bp = NULL;
mode |= PPP_TOSS;
continue;
}
tail_bp = tail_bp->next;
cp = tail_bp->data;
}
/* Store the byte, increment counts */
*cp++ = c;
tail_bp->cnt++;
calc_fcs = pppfcs(calc_fcs, c);
}
/* clean up afterward */
free_p(&raw_bp);
free_p(&head_bp);
ifp->rxproc = NULL;
}
#ifdef TURBOC_SWITCH_BUG
#pragma option -G-
#endif
/* Process incoming PPP packets */
/* (called from network task) */
void
ppp_proc(ifp,bpp)
struct iface *ifp;
struct mbuf **bpp;
{
struct ppp_s *ppp_p;
struct ipcp_s *ipcp_p;
struct ppp_hdr ph;
uint16 negotiated = FALSE;
if ( ifp == NULL ) {
logmsg(-1, "ppp_proc: missing iface" );
return;
}
if ( *bpp == NULL ) {
trace_log(ifp, "ppp_proc: missing buffer" );
return;
}
ppp_p = ifp->edv;
ppp_p->InRxOctetCount += len_p(*bpp) + 2; /* count FCS bytes */
/* Use negotiated values if LCP finished */
if (ppp_p->fsm[Lcp].state == fsmOPENED) {
struct lcp_s *lcp_p = ppp_p->fsm[Lcp].pdv;
negotiated = lcp_p->local.work.negotiate;
}
/* HDLC address and control fields may be compressed out */
if ((byte_t)(*bpp)->data[0] != HDLC_ALL_ADDR) {
if (!(negotiated & LCP_N_ACFC)) {
ppp_skipped( ppp_p, bpp, "missing ALL address" );
ppp_p->InFrame++;
return;
}
} else if ((byte_t)(*bpp)->data[1] != HDLC_UI) {
if (!(negotiated & LCP_N_ACFC)
|| !(negotiated & LCP_N_PFC)) {
ppp_skipped( ppp_p, bpp, "missing UI" );
ppp_p->InFrame++;
return;
}
} else {
/* skip address/control fields */
pull16(bpp);
}
/* Initialize the expected header */
ph.addr = HDLC_ALL_ADDR;
ph.control = HDLC_UI;
ph.protocol = PULLCHAR(bpp);
/* First byte of PPP protocol field may be compressed out */
if ( ph.protocol & 0x01 ) {
if (!(negotiated & LCP_N_PFC)) {
ppp_skipped( ppp_p, bpp, "missing upper protocol byte" );
ppp_p->InFrame++;
return;
}
} else {
ph.protocol = (ph.protocol << 8) | PULLCHAR(bpp);
/* Second byte of PPP protocol field must be odd */
if ( !(ph.protocol & 0x01) ) {
ppp_skipped( ppp_p, bpp, "missing lower protocol byte" );
ppp_p->InFrame++;
return;
}
}
switch(ph.protocol) {
case PPP_IP_PROTOCOL: /* Regular IP */
if ( ppp_p->fsm[IPcp].state != fsmOPENED ) {
ppp_error( ppp_p, bpp, "not open for IP traffic" );
ppp_p->InError++;
break;
}
ip_route(ifp,bpp,0);
break;
case PPP_COMPR_PROTOCOL: /* Van Jacobson Compressed TCP/IP */
if ( ppp_p->fsm[IPcp].state != fsmOPENED ) {
ppp_skipped( ppp_p, bpp, "not open for Compressed TCP/IP traffic" );
ppp_p->InError++;
break;
}
ipcp_p = ppp_p->fsm[IPcp].pdv;
if (!(ipcp_p->local.work.negotiate & IPCP_N_COMPRESS)) {
ppp_skipped( ppp_p, bpp, "Compressed TCP/IP not enabled" );
ppp_p->InError++;
break;
}
if ( slhc_uncompress(ipcp_p->slhcp, bpp) <= 0 ) {
ppp_error( ppp_p, bpp, "Compressed TCP/IP packet error" );
ppp_p->InError++;
break;
}
ip_route(ifp,bpp,0);
break;
case PPP_UNCOMP_PROTOCOL: /* Van Jacobson Uncompressed TCP/IP */
if ( ppp_p->fsm[IPcp].state != fsmOPENED ) {
ppp_skipped( ppp_p, bpp, "not open for Uncompressed TCP/IP traffic" );
ppp_p->InError++;
break;
}
ipcp_p = ppp_p->fsm[IPcp].pdv;
if (!(ipcp_p->local.work.negotiate & IPCP_N_COMPRESS)) {
ppp_skipped( ppp_p, bpp, "Uncompressed TCP/IP not enabled" );
ppp_p->InError++;
break;
}
if ( slhc_remember(ipcp_p->slhcp, bpp) <= 0 ) {
ppp_error( ppp_p, bpp, "Uncompressed TCP/IP packet error" );
ppp_p->InError++;
break;
}
ip_route(ifp,bpp,0);
break;
case PPP_LCP_PROTOCOL: /* Link Control Protocol */
ppp_p->InNCP[Lcp]++;
fsm_proc(&(ppp_p->fsm[Lcp]),bpp);
break;
case PPP_PAP_PROTOCOL: /* Password Authenticate Protocol */
if (ppp_p->phase != pppAP
&& ppp_p->phase != pppREADY) {
ppp_error( ppp_p, bpp, "not ready for Authentication" );
ppp_p->InError++;
break;
}
ppp_p->InNCP[Pap]++;
pap_proc(&(ppp_p->fsm[Pap]),bpp);
break;
case PPP_IPCP_PROTOCOL: /* IP Control Protocol */
if (ppp_p->phase != pppREADY) {
ppp_error( ppp_p, bpp, "not ready for IPCP traffic" );
ppp_p->InError++;
break;
}
ppp_p->InNCP[IPcp]++;
fsm_proc(&(ppp_p->fsm[IPcp]),bpp);
break;
default:
if ( ppp_p->trace )
trace_log(ppp_p->iface, "%s PPP Unknown packet protocol: %x;",
ppp_p->iface->name,
ph.protocol);
ppp_p->InUnknown++;
/* Build Protocol Reject packet:
* put the header back on ...
*/
htonppp(&ph,bpp);
/* ... then pull off the address and control fields ... */
pull16(bpp);
/* ... and send it as an LCP packet */
fsm_send( &(ppp_p->fsm[Lcp]), PROT_REJ, 0, bpp );
break;
};
}
#ifdef TURBOC_SWITCH_BUG
#pragma option -G
#endif
/************************************************************************/
/* Keep track of changes in I-O status */
/* (called through iface iostatus vector) */
static int
ppp_iostatus( ifp, command, value )
struct iface *ifp;
int command;
int32 value;
{
struct ppp_s *ppp_p = ifp->edv;
switch ( command ) {
case PARAM_UP:
ppp_log( ppp_p, "Physical layer up" );
if ( ppp_p->phase == pppDEAD ) {
ppp_p->phase = pppLCP;
}
fsm_start( &(ppp_p->fsm[Lcp]) );
return 0;
case PARAM_DOWN:
ppp_log( ppp_p, "Physical layer down" );
fsm_down( &(ppp_p->fsm[Lcp]) );
ppp_p->phase = pppDEAD;
return 0;
};
return -1;
}
static int
ppp_discard(
struct iface *ifp,
struct mbuf **bpp
){
struct ppp_s *ppp_p = ifp->edv;
return fsm_send(&(ppp_p->fsm[Lcp]), DISCARD_REQ, 0, bpp);
}
static int
ppp_echo(
struct iface *ifp,
struct mbuf **bpp
){
struct ppp_s *ppp_p = ifp->edv;
return fsm_send(&(ppp_p->fsm[Lcp]), ECHO_REQ, 0, bpp);
}
/****************************************************************************/
/* Initialize PPP control structures for a Point-to-Point interface */
int
ppp_init(ifp)
struct iface *ifp;
{
struct ppp_s *ppp_p;
char *ifn;
/* Setup for Point-to-Point Protocol */
ifp->ioctl = asy_ioctl;
ppp_p = callocw(1,sizeof(struct ppp_s));
ifp->edv = ppp_p;
ifp->iostatus = ppp_iostatus;
ifp->raw = ppp_raw;
ifp->show = ppp_show;
ifp->echo = ppp_echo;
ifp->discard = ppp_discard;
ppp_p->iface = ifp;
ppp_p->phase = pppDEAD;
lcp_init(ppp_p);
pap_init(ppp_p);
ipcp_init(ppp_p);
ifp->rxproc = newproc( ifn = if_name( ifp, " receive" ),
320, ppp_recv, ifp->dev, ifp, NULL, 0);
free(ifn);
return 0;
}
int
ppp_free(ifp)
struct iface *ifp;
{
struct ppp_s *ppp_p = ifp->edv;
int fsmi;
alert( ifp->rxproc, 1 );
for ( fsmi = Lcp; fsmi < fsmi_Size; ) {
fsm_free( &(ppp_p->fsm[fsmi++]) );
}
free( ppp_p->peername );
free( ppp_p );
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -