📄 netppp.c
字号:
pc->vjEnabled = vjcomp;
pc->vjComp.compressSlot = cidcomp;
pc->vjComp.maxSlotIndex = maxcid;
PPPDEBUG((LOG_INFO, TL_PPP, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d",
vjcomp, cidcomp, maxcid));
#endif
return 0;
}
/*
* sifup - Config the interface up and enable IP packets to pass.
*/
#pragma argsused
int sifup(int pd)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, TL_PPP, "sifup[%d]: bad parms", pd));
} else {
pc->if_up = 1;
pc->errCode = 0;
}
return st;
}
/*
* sifnpmode - Set the mode for handling packets for a given NP.
*/
#pragma argsused
int sifnpmode(int u, int proto, enum NPmode mode)
{
return 0;
}
/*
* sifdown - Config the interface down and disable IP.
*/
#pragma argsused
int sifdown(int pd)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, TL_PPP, "sifup[%d]: bad parms", pd));
} else
pc->if_up = 0;
return st;
}
/*
* sifaddr - Config the interface IP addresses and netmask.
*/
#pragma argsused
int sifaddr(
int u, /* Interface unit ??? */
u_int32_t o, /* Our IP address ??? */
u_int32_t h, /* IP subnet mask ??? */
u_int32_t m /* IP broadcast address ??? */
)
{
return 1;
}
/*
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
*/
#pragma argsused
int cifaddr(
int u, /* Interface unit ??? */
u_int32_t o, /* Our IP address ??? */
u_int32_t h /* IP broadcast address ??? */
)
{
return 1;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
#pragma argsused
int sifdefaultroute(int u, u_int32_t l, u_int32_t g)
{
ipSetDefault(l, g, IFT_PPP, u);
return !0;
}
/*
* cifdefaultroute - delete a default route through the address given.
*/
#pragma argsused
int cifdefaultroute(int u, u_int32_t l, u_int32_t g)
{
ipClearDefault();
return !0;
}
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
/* The main PPP process function. This implements the state machine according
* to section 4 of RFC 1661: The Point-To-Point Protocol. */
static void pppMain(void *pd)
{
PPPControl *pc = &pppControl[(int)pd];
NBuf *curNBuf;
/*
* Start the connection and handle incoming events (packet or timeout).
*/
trace(LOG_NOTICE, "Connecting %s <--> %s", pc->ifname, nameForDevice(pc->fd));
lcp_lowerup((int)pd);
lcp_open((int)pd); /* Start protocol */
while (lcp_phase[(int)pd] != PHASE_DEAD) {
if (pc->kill_link) {
/* This will leave us at PHASE_DEAD. */
lcp_close(0, "User request");
pc->kill_link = 0;
}
else {
nGet(pc->fd, &curNBuf, MAXKILLDELAY);
avRandomize();
if (curNBuf != NULL) {
pppInput((int)pd, curNBuf);
/* curNBuf is invalid now so we don't need to free it. */
}
}
}
OSTaskDel(OS_PRIO_SELF);
}
/*
* Pass the processed input packet to the appropriate handler.
*/
static void pppDispatch(int pd, NBuf *nb, u_int protocol)
{
if (nb != NULL) {
switch(protocol) {
case PPP_LCP: /* Link Control Protocol */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: lcp in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
/* XXX Assume that LCP packet fits in single nBuf. */
lcp_protent.input(pd, nb->data, nb->len);
nFreeChain(nb);
break;
case PPP_IPCP: /* IP Control Protocol */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: ipcp in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
/* XXX Assume that IPCP packet fits in single nBuf. */
ipcp_protent.input(pd, nb->data, nb->len);
nFreeChain(nb);
break;
case PPP_PAP: /* Password Authentication Protocol */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: pap in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
pap_protent.input(pd, nb->data, nb->len);
nFreeChain(nb);
break;
case PPP_VJC_COMP: /* VJ compressed TCP */
#if VJ_SUPPORT > 0
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: vj_comp in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
/*
* Clip off the VJ header and prepend the rebuilt TCP/IP header and
* pass the result to IP.
*/
if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
ipInput(nb, IFT_PPP, pd);
} else {
/* Something's wrong so drop it. */
PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
"pppDispatch[%d]: Dropping VJ compressed", pd));
nFreeChain(nb);
}
#else
/* No handler for this protocol so drop the packet. */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: drop VJ Comp in %d:.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
nFreeChain(nb);
#if STATS_SUPPORT > 0
pppStats.PPPderrors++;
#endif
#endif
break;
case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
#if VJ_SUPPORT > 0
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: vj_un in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
/*
* Process the TCP/IP header for VJ header compression and then pass
* the packet to IP.
*/
if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
ipInput(nb, IFT_PPP, pd);
} else {
/* Something's wrong so drop it. */
PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
"pppDispatch[%d]: Dropping VJ uncompressed", pd));
nFreeChain(nb);
}
#else
/* No handler for this protocol so drop the packet. */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: drop VJ UnComp in %d:.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
nFreeChain(nb);
#if STATS_SUPPORT > 0
pppStats.PPPderrors++;
#endif
#endif
break;
case PPP_IP: /* Internet Protocol */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: ip in %d:%.*H",
pd, nb->len, MIN(nb->len * 2, 40), nb->data));
ipInput(nb, IFT_PPP, pd);
break;
case PPP_AT: /* AppleTalk Protocol */
case PPP_COMP: /* compressed packet */
case PPP_ATCP: /* AppleTalk Control Protocol */
case PPP_CCP: /* Compression Control Protocol */
case PPP_LQR: /* Link Quality Report protocol */
case PPP_CHAP: /* Cryptographic Handshake Auth. Protocol */
case PPP_CBCP: /* Callback Control Protocol */
default:
/* No handler for this protocol so drop the packet. */
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppDispatch[%d]: drop 0x%X in %d:%.*H",
pd, protocol, nb->len, MIN(nb->len * 2, 40), nb->data));
nFreeChain(nb);
#if STATS_SUPPORT > 0
pppStats.PPPderrors++;
#endif
break;
}
}
}
/*
* Drop the input packet.
*/
static void pppDrop(PPPControl *pc)
{
if (pc->inHead != NULL) {
PPPDEBUG((LOG_INFO, TL_PPP, "pppDrop: %d:%.*H",
pc->inHead->len,
min(60, pc->inHead->len * 2),
pc->inHead->data));
nFreeChain(pc->inHead);
pc->inHead = NULL;
pc->inTail = NULL;
}
#if VJ_SUPPORT > 0
vj_uncompress_err(&pc->vjComp);
#endif
}
/*
* Process a received octet string.
*/
static void pppInProc(int pd, u_char *s, int l)
{
PPPControl *pc = &pppControl[pd];
NBuf *nextNBuf;
u_char curChar;
while (l-- > 0) {
curChar = *s++;
/* Handle special characters. */
if (ESCAPE_P(pc->inACCM, curChar)) {
/* Check for escape sequences. */
/* XXX Note that this does not handle an escaped 0x5d character which
* would appear as an escape character. Since this is an ASCII ']'
* and there is no reason that I know of to escape it, I won't complicate
* the code to handle this case. GLL */
if (curChar == PPPESCAPE)
pc->inEscaped = !0;
/* Check for the flag character. */
else if (curChar == PPPFLAG) {
/* If this is just an extra flag character, ignore it. */
if (pc->inState == PDADDRESS)
;
/* If we haven't received the packet header, drop what has come in. */
else if (pc->inState < PDDATA) {
PPPDEBUG((pc->traceOffset + LOG_WARNING, TL_PPP,
"pppInProc[%d]: Dropping incomplete packet %d",
pd, pc->inState));
pppDrop(pc);
}
/* If the fcs is invalid, drop the packet. */
else if (pc->inFCS != PPP_GOODFCS) {
PPPDEBUG((pc->traceOffset + LOG_INFO, TL_PPP,
"pppInProc[%d]: Dropping bad fcs 0x%X proto=x%X",
pd, pc->inFCS, pc->inProtocol));
pppDrop(pc);
#if STATS_SUPPORT > 0
pppStats.PPPierrors++;
#endif
}
/* Otherwise it's a good packet so pass it on. */
else {
/* Trim off the checksum. */
pc->inTail->len -= 2;
pc->inLen -= 2;
/* Update the packet header. */
pc->inHead->chainLen = pc->inLen;
/* Dispatch the packet thereby consuming it. */
pppDispatch(pd, pc->inHead, pc->inProtocol);
pc->inHead = NULL;
pc->inTail = NULL;
#if STATS_SUPPORT > 0
pppStats.PPPipackets++;
#endif
}
/* Prepare for a new packet. */
pc->inFCS = PPP_INITFCS;
pc->inState = PDADDRESS;
pc->inEscaped = 0;
}
/* Other characters are usually control characters that may have
* been inserted by the physical layer so here we just drop them. */
else {
PPPDEBUG((pc->traceOffset + LOG_WARNING, TL_PPP,
"pppInProc[%d]: Dropping ACCM char <%d>", pd, curChar));
}
}
/* Process other characters. */
else {
/* Unencode escaped characters. */
if (pc->inEscaped) {
pc->inEscaped = 0;
curChar ^= PPPESCMASK;
}
/* Having removed transparency encoding and physical layer control characters,
* we can update the frame check sequence nunber. */
pc->inFCS = PPP_FCS(pc->inFCS, curChar);
/* Process character relative to current state. */
switch(pc->inState) {
case PDIDLE: /* Idle state - waiting. */
/* Drop the character. */
break;
case PDSTART: /* Process start flag. */
/* Drop the character - we would have processed a flag character
* above. */
break;
case PDCONTROL: /* Process control field. */
/* If we don't get a valid control code, restart. */
if (curChar == PPPCONTROL) {
pc->inState = PDPROTOCOL1;
}
else {
PPPDEBUG((pc->traceOffset + LOG_WARNING, TL_PPP,
"pppInProc[%d]: Invalid control <%d>", pd, curChar));
pc->inState = PDSTART;
}
break;
case PDADDRESS: /* Process address field. */
if (curChar == PPPADDRESS) {
pc->inState = PDCONTROL;
break;
}
/* Else assume compressed address and control fields so
* fall through to get the protocol... */
case PDPROTOCOL1: /* Process protocol field 1. */
/* If the lower bit is set, this is the end of the protocol
* field. */
if (curChar & 1) {
pc->inProtocol = curChar;
pc->inState = PDDATA;
}
else {
pc->inProtocol = (u_int)curChar << 8;
pc->inState = PDPROTOCOL2;
}
break;
case PDPROTOCOL2: /* Process protocol field 2. */
pc->inProtocol |= curChar;
pc->inState = PDDATA;
break;
case PDDATA: /* Process data byte. */
/* Make space to receive processed data. */
if (pc->inTail == NULL || nTRAILINGSPACE(pc->inTail) <= 0) {
/* If we haven't started a packet, we need a packet header. */
nGET(nextNBuf);
if (nextNBuf == NULL) {
/* No free buffers. Drop the input packet and let the
* higher layers deal with it. Continue processing
* the received nBuf chain in case a new packet starts. */
PPPDEBUG((LOG_ERR, TL_PPP, "pppInProc[%d]: NO FREE MBUFS!", pd));
pppDrop(pc);
pc->inState = PDSTART; /* Wait for flag sequence. */
pc->inFCS = PPP_INITFCS;
} else {
*(nextNBuf->data) = curChar;
nextNBuf->len = 1;
nextNBuf->nextBuf = NULL;
if (pc->inHead == NULL) {
pc->inHead = nextNBuf;
pc->inLen = 1;
}
else { /* Since if inHead is not NULL, then neither is inTail! */
pc->inTail->nextBuf = nextNBuf;
pc->inLen++;
}
pc->inTail = nextNBuf;
}
}
/* Load character into buffer. */
else {
pc->inTail->data[pc->inTail->len++] = curChar;
pc->inLen++;
}
break;
}
}
}
}
/*
* pppMPutC - append given character to end of given nBuf. If the character
* needs to be escaped, do so. If nBuf is full, append another.
* Return the current nBuf.
*/
static NBuf *pppMPutC(u_char c, ext_accm *outACCM, NBuf *nb)
{
NBuf *tb = nb;
/* Make sure there is room for the character and an escape code.
* Sure we don't quite fill the buffer if the character doesn't
* get escaped but is one character worth complicating this? */
/* Note: We assume no packet header. */
if (nb && (&nb->body[NBUFSZ] - (nb->data + nb->len)) < 2) {
nGET(tb);
if (tb) {
nb->nextBuf = tb;
tb->len = 0;
}
nb = tb;
}
if (nb) {
if (ESCAPE_P(*outACCM, c)) {
*(nb->data + nb->len++) = PPP_ESCAPE;
*(nb->data + nb->len++) = c ^ PPP_TRANS;
}
else
*(nb->data + nb->len++) = c;
}
return tb;
}
/*
* pppMPutRaw - append given character to end of given nBuf without escaping
* it. If nBuf is full, append another.
* This is normally used to add the flag character to a packet.
* Return the current nBuf.
*/
static NBuf *pppMPutRaw(u_char c, NBuf *nb)
{
NBuf *tb = nb;
/* Make sure there is room for the character and an escape code.
* Sure we don't quite fill the buffer if the character doesn't
* get escaped but is one character worth complicating this? */
/* Note: We assume no packet header. */
if (nb && (&nb->body[NBUFSZ] - (nb->data + nb->len)) < 2) {
nGET(tb);
if (tb) {
nb->nextBuf = tb;
tb->len = 0;
}
nb = tb;
}
if (nb) {
*(nb->data + nb->len++) = c;
}
return tb;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -