📄 pppfsm.c
字号:
/* Initially, don't let line driver auto-decompress incoming
* comp/ac bytes.
*/
mppp->sc_flags |= SC_REJ_COMP_AC; /* set reject bit */
/* Clear settings from previous connections on this structure */
mppp->bad_fcs = 0;
mppp->io_errors = 0;
mppp->tmo_tick = 0;
mppp->tmr_sets = 0;
mppp->tmr_cleared = 0;
mppp->tmr_fired = 0;
mppp->bytes_in = 0;
mppp->pkts_in = 0;
mppp->bytes_out = 0;
mppp->pkts_out = 0;
mppp->pppflags = 0;
mppp->auth = NULL;
return;
}
/* FUNCTION: ppp_sendctl()
*
* PPP control packet send routine
* copy code & data to packet buffer and send via link
*
* PARAM1: M_PPP mppp - session on which to send
* PARAM2: int pcode - protocol to send (LCP, ICMP, etc)
* PARAM3: u_char code - packet code (CONREQ, CONFNAK, etc)
* PARAM4: u_char * data - data to attach or NULL if none.
* PARAM5: int len - length of data if data in non-NULL
* PARAM6: u_char Id - Id of packet to send
*
* RETURNS: 0 if OK or ENP_ error code
*/
unshort ppp_prots[2] =
{
PPP_LCP,
PPP_IPCP,
};
int
ppp_sendctl(M_PPP mppp, int pcode, u_char code, u_char * data, int len, u_char Id)
{
PACKET pkt;
u_char * p;
/* get a packet big enough for data and various headers */
LOCK_NET_RESOURCE(FREEQ_RESID);
pkt = pk_alloc(len + 6 + MaxLnh);
UNLOCK_NET_RESOURCE(FREEQ_RESID);
if(!pkt)
return ENP_NOBUFFER;
/* build the PPP header in the send packet. Auth pprotocols build
* their own headers, so skip them.
*/
p = (u_char*)pkt->nb_prot; /* build packet in send buffer */
if(pcode != AUTH_STATE)
{
p = ppp_putshort(p, ppp_prots[pcode]);
*p++ = code;
*p++ = Id;
p = ppp_putshort(p, (unshort)(len + 4));
pkt->nb_plen = 6; /* pkt now has 6 bytes of header */
}
if(data) /* copy in any data passed, like */
{
MEMCPY(p, data, len); /* the CI option string or auth pkt */
pkt->nb_plen += len;
}
putq(&mppp->fastq, (qp)pkt); /* Into the control pkt output queue */
return(ppp_allpktsend(mppp));
}
/* FUNCTION: ppp_allpktsend()
*
* ppp_allpktsend - Try to initiate the next send operation for the ppp
* link. This should be called each time a packet is placed in one of the
* PPP send queues and also whenever a send completes.
*
* PARAM1: M_PPP mppp
*
* RETURNS: 0 if OK or ENP_ error code.
*/
int
ppp_allpktsend(M_PPP mppp)
{
PACKET pkt;
int datapkt; /* bool for control or data */
unshort prot;
struct ip * pip;
if(mppp->pppflags & PPP_SENDING) /* currently sending on this link? */
return 0;
/* check queues for packets to send. First check the "fast" queue,
* where the control (LCP, IPCP) packets get queued for sending and
* send from this queue first. If there are no control packet then
* check for data (IP) packets. Before sending data packets make
* sure IPCP has come up on the link. Also try to VJ compress them
* at this point.
*/
if(mppp->fastq.q_len)
{
pkt = (PACKET)getq(&mppp->fastq);
datapkt = FALSE;
}
else if(mppp->dataq.q_len) /* got IP? */
{
/* handle case where the link is still connecting */
if(mppp->states[IPCP_STATE] != ST_OPENED)
return ENP_SEND_PENDING; /* can't send IP pkt yet */
datapkt = TRUE;
pkt = (PACKET)getq(&mppp->dataq);
pip = (struct ip *)(pkt->nb_prot + 2);
prot = ppp_getshort((u_char*)pkt->nb_prot); /* get PPP prot */
/* Handle case where DHCP is still trying to get an IP address */
if(mppp->ifp->n_ipaddr == 0)
{
/* put non broadcast pkts back in the queue; fall though
* to send broadcasts (maybe DHCP pkts)
*/
if((pip->ip_dest != 0xFFFFFFFF) &&
(pip->ip_dest != mppp->ifp->n_netbr42))
{
// ConPrintf("allpktsend - DHCP pending?\n");
putq(&mppp->dataq, (qp)pkt); /* return pkt to dataq */
return ENP_SEND_PENDING;
}
}
/* Handle case where the dequeued IP packet originated on this machine
* before the link was up and thus was assigned a source IP address of
* zero.
*/
if(pip->ip_src == 0) /* if src IP is zero... */
ppp_set_ipaddr(pkt); /* stuff ifaces IP as source */
#ifdef USE_MODEM
/* Save IP info of this packet to assist in detecting
* looped-back modems, VJ decisions, and DHCP packets.
*/
if(prot == PPP_IP)
{
mppp->last_ip_src = pip->ip_src;
mppp->last_ip_dest = pip->ip_dest;
mppp->last_ip_id = pip->ip_id;
}
#endif /* USE_MODEM */
#ifdef PPP_VJC
/* see if we should do VJ compression on this pkt */
if((mppp->sc_flags & SC_COMP_TCP) && /* link doing VJ? */
(prot == PPP_IP) && /* pkt is IP? */
(pip->ip_prot == 6)) /* is next layer TCP? */
{
pkt->nb_prot += 2; /* bump pkt past prot code to IP */
pkt->nb_plen -= 2;
prot = vj_compress_tcp((u_char**)(&(pkt->nb_prot)),
&(pkt->nb_plen),
(struct vj_ip*)pip,
&mppp->sc_comp,
!(mppp->sc_flags & SC_NO_TCP_CCID));
pkt->nb_prot -= 2; /* bump pkt back to prot code slot */
pkt->nb_plen += 2; /* include code in size */
ppp_putshort((u_char*)pkt->nb_prot, prot); /* install VJ prot code */
}
#endif /* PPP_VJC */
}
else
return 0; /* nothing to do... */
/* see if we need to dump pkt to log */
//ConPrintf("link %p sending:", mppp);
ppp_hexdump((u_char*)pkt->nb_prot, pkt->nb_plen);
#ifdef LOSSY_IO
if(NDEBUG & LOSSY_TX)
{
if(in_lastloss++ == in_lossrate)
{
//ConPrintf("PPP LOSSY_IO dropping TX (link %p)\n", mppp);
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt); /* punt packet */
UNLOCK_NET_RESOURCE(FREEQ_RESID);
in_lastloss = (int)(cticks & 0x07) - 4; /* pseudo random reset */
return 0; /* act as if we sent OK */
}
}
#endif /* LOSSY_IO */
if(mppp->line.ln_state != LN_CONNECTED)
{
//ConPrintf("ppp_allpktsend (%p): lost line\n", mppp);
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free(pkt);
UNLOCK_NET_RESOURCE(FREEQ_RESID);
return ENP_SENDERR;
}
#ifdef PPP_MULTILINK
/* for multilink connections see if we should fragment it */
if((mppp->pppflags & ML_IPCP) && /* It's a ML bundle */
(datapkt) && /* and it's not a control pkt */
(mppp->ml_numlinks > 1) && /* and we have multile links up */
(pkt->nb_plen > mppp->ml_frag_size)) /* and it's a big pkt */
{
return( pppml_sendpkt(mppp, pkt) );
}
#else
USE_ARG(datapkt);
#endif /* PPP_MULTILINK */
return(ppp_lower_send(mppp, pkt));
}
/* FUNCTION: ppp_lower_send()
*
* lowest level pkt oriented send routine. ML can use this to
* send fragments. This either passed the packet to the line pkt
* sender or to the PPP HDLC-like char code handler.
*
* PARAM1: M_PPP mppp
* PARAM2: PACKET pkt
*
* RETURNS: 0 if OK, or error code from line call.
*/
int
ppp_lower_send(M_PPP mppp, PACKET pkt)
{
int err;
/* send packet. If the line supports a packet send routine then use it,
* else send it a byte at a time and free the packet.
*/
#if PPPFSM_DEBUG
Printu("\r\n=======ppp_lower_send======\r\n");
PrintString('x',pkt->nb_prot,pkt->nb_plen);
Printu("\r\n================================\r\n");
#endif
mppp->pppflags |= PPP_SENDING; /* set sending flag bit */
if(mppp->line.ln_write)
err = mppp->line.ln_write(&mppp->line, pkt);
else
{
#ifdef PPP_CHARIO
err = ppp_sendchars(mppp, pkt);
#else
dtrap("pppfsm 4\n"); /* bad configuration */
err = ENP_LOGIC;
#endif /* PPP_CHARIO */
}
if(err == 0)
{
mppp->pkts_out++;
mppp->bytes_out += pkt->nb_plen;
}
mppp->pppflags &= ~PPP_SENDING; /* clear sending flag bit */
return err; /* OK return */
}
/* externally callable PPP FSM state change routines */
/* FUNCTION: ppp_lowerup()
*
* PARAM1: M_PPP mppp - session for state change
* PARAM2: int pcode - code for protocol we want to start.
*
* RETURNS: void
*/
void
ppp_lowerup(M_PPP mppp, int pcode)
{
//ConPrintf("lowerup: (link %p) %s\n", mppp, prots[pcode]);
switch (pcode)
{
case IPCP_STATE:
//break;/////ppp_debug
/* this handles complicating conditions like us being the server
* and membership in a multilink bundle.
*/
#ifdef PPP_MULTILINK
/* See if this is LCP joining an existing Multilink Bundle. */
if(mppp->lcp_hisoptions.neg_ml_mru)
{
/* Add link to bundle. If it joined an existing bundle then
* don't start IPCP on this mppp.
*/
if(pppml_link(mppp) != 0)
return;
}
#endif /* PPP_MULTILINK */
ppp_fsm(mppp, pcode, EV_UP, NULL, 0);
/* If we're server then do the open too. */
if(mppp->pppflags & PPP_SERVER)
ppp_open(mppp, IPCP_STATE);
#ifdef PPP_MAKEPEERADDR
/* If we don't have an address for the peer,
* then make one up in case that we can hand out if asked.
* We do this by making a delta of one from our IP interface's
* IP address -- +1 if that won't lead to an all-ones host address,
* else -1.
* This may not be the right thing to do, so use it with care!
* ...but it sometimes works well for point-to-point links.
*/
if ((mppp->pppflags & PPP_SERVER) &&
(mppp->ipcp_wantoptions.hisaddr == 0) &&
(mppp->ifp) && (mppp->ifp->n_ipaddr))
{
ip_addr tmpip = ntohl(mppp->ifp->n_ipaddr);
if ((tmpip & 0x000000ff) > 253)
mppp->ipcp_wantoptions.hisaddr = htonl(tmpip - 1);
else
mppp->ipcp_wantoptions.hisaddr = htonl(tmpip + 1);
}
#endif /* PPP_MAKEPEERADDR */
break;
case AUTH_STATE:
/* Authentication protocls have their own state machines.
* start the authentication now. When complete this will do the
* lowerup call for IPCP.
*/
mppp->auth->auth_init(mppp);
mppp->auth->auth_lowerup(mppp);
if(mppp->pppflags & PPP_SERVER)
mppp->auth->auth_peer(mppp);
else
mppp->auth->auth_with_peer(mppp);
break;
case LCP_STATE:
ppp_fsm(mppp, pcode, EV_UP, NULL, 0);
break;
default:
dtrap("pppfsm 5\n"); /* bad protocol index code */
}
return;
}
/* FUNCTION: ppp_lowerdown()
*
* PARAM1: M_PPP mppp - session for state change
* PARAM2: int pcode - code for protocol we want to shut down.
*
* RETURNS: void
*/
void
ppp_lowerdown(M_PPP mppp, int pcode)
{
//ConPrintf("lowerdown (link %p): %s\n", mppp, prots[pcode]);
/* do this layer's FSM actions for lowerdown */
ppp_fsm(mppp, pcode, EV_DOWN, NULL, 0);
}
/* FUNCTION: ppp_open()
*
* PARAM1: M_PPP mppp - session for state change
* PARAM2: int pcode - code for protocol we want to open.
*
* RETURNS: void
*/
void
ppp_open(M_PPP mppp, int pcode)
{
//ConPrintf("open (link %p): %s\n", mppp, prots[pcode]);
#ifdef PPP_MULTILINK
/* if this is an IPCP open and the link is a multilink slave,
* then ignore this and don't open the IPCP layer.
*/
if((pcode == IPCP_STATE) &&
((mppp->pppflags & (ALLOW_ML|ML_IPCP|ML_LCP)) == (ALLOW_ML|ML_LCP)))
{
return;
}
#endif
/* do this layer's FSM actions for open */
ppp_fsm(mppp, pcode, EV_OPEN, NULL, 0);
}
/* FUNCTION: ppp_close()
*
* PARAM1: M_PPP mppp - session for state change
* PARAM2: int pcode - code for protocol we want to close.
*
* RETURNS: void
*/
void
ppp_close(M_PPP mppp, int pcode)
{
//ConPrintf("close (link %p): %s\n", mppp, prots[pcode]);
/* flush any packets stuck in the data queue */
while(mppp->dataq.q_head)
{
LOCK_NET_RESOURCE(FREEQ_RESID);
pk_free((PACKET)getq(&mppp->dataq));
UNLOCK_NET_RESOURCE(FREEQ_RESID);
}
/* clear the sending flag in case he thinks he's sending. */
mppp->pppflags &= ~PPP_SENDING;
/* do this layer's FSM actions for close */
ppp_fsm(mppp, pcode, EV_CLOSE, NULL, 0);
}
/* FUNCTION: ppp_hexdump()
*
* PARAM1: u_char *b
* PARAM2: int l
*
* RETURNS: void
*/
int ppp_hexmax = 100; /* MAX length of debug hexdumps */
void
ppp_hexdump(u_char * b, int length)
{
#ifndef PPP_NOHEXDUMP
if(ppp_hexmax == 0)
return;
if(length > ppp_hexmax)
length = ppp_hexmax;
/* If logging is on then ConPrintf hexdump of the pkt */
if((PPPDEBUG & (PPPD_CONS | PPPD_FILE)) != 0)
{
while(length--) ;
// ConPrintf("%02x ", *b++);
//ConPrintf("\n");
}
#else
USE_ARG(b);
#endif /* PPP_NOHEXDUMP */
}
#endif /* USE_PPP whole file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -