📄 netppp.c
字号:
}
/* Close a PPP connection and release the descriptor.
* Any outstanding packets in the queues are dropped.
* Return 0 on success, an error code on failure. */
int pppClose(int pd)
{
PPPControl *pc = &pppControl[pd];
int st = 0;
/* Disconnect */
pc->kill_link = !0;
pc->traceOffset = 0;
while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
msleep(500);
if (buttonStatus() == YESNOBUTTON)
st = PPPERR_USER;
}
/* Reset fd line discipline. In our case, the framing character. */
if (ioctl(pc->fd, SETFRAME, &pppControl[pd].oldFrame) < 0)
st = PPPERR_DEVICE;
pc->openFlag = 0;
return st;
}
/* Send a packet on the given connection.
* Return 0 on success, an error code on failure. */
#pragma argsused
int pppOutput(int pd, u_short protocol, NBuf *nb)
{
PPPControl *pc = &pppControl[pd];
u_int fcsOut = PPP_INITFCS;
NBuf *headMB = NULL, *tailMB = NULL, *tnb;
int st = 0;
u_char c = 0;
int n;
u_char *sPtr;
/* Grab an output buffer. */
nGET(headMB);
if (headMB == NULL) {
st = PPPERR_ALLOC;
PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: first alloc fail", pd));
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
/* Validate parameters. */
/* We let any protocol value go through - it can't hurt us
* and the peer will just drop it if it's not accepting it. */
} else if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !nb) {
st = PPPERR_PARAM;
PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: bad parms prot=%d nb=%P",
pd, protocol, nb));
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
/* Check that the link is up. */
} else if (lcp_phase[pd] == PHASE_DEAD) {
PPPDEBUG((LOG_ERR, TL_PPP, "pppOutput[%d]: link not up", pd));
#if STATS_SUPPORT > 0
pppStats.PPPderrors++;
#endif
st = PPPERR_OPEN;
} else {
#if VJ_SUPPORT > 0
/*
* Attempt Van Jacobson header compression if VJ is configured and
* this is an IP packet.
*/
if (protocol == PPP_IP && pc->vjEnabled) {
switch (vj_compress_tcp(&pc->vjComp, nb)) {
case TYPE_IP:
/* No change...
protocol = PPP_IP_PROTOCOL;
*/
break;
case TYPE_COMPRESSED_TCP:
protocol = PPP_VJC_COMP;
break;
case TYPE_UNCOMPRESSED_TCP:
protocol = PPP_VJC_UNCOMP;
break;
default:
PPPDEBUG((LOG_WARNING, TL_PPP, "pppOutput[%d]: bad IP packet", pd));
#if STATS_SUPPORT > 0
pppStats.PPPderrors++;
#endif
return PPPERR_PROTOCOL;
}
}
#endif
headMB->len = 0;
tailMB = headMB;
/* Build the PPP header. */
if (diffTime(pc->lastXMit) <= MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
if (!pc->accomp) {
fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
tailMB = pppMPutC(PPP_ALLSTATIONS, &pc->outACCM, tailMB);
fcsOut = PPP_FCS(fcsOut, PPP_UI);
tailMB = pppMPutC(PPP_UI, &pc->outACCM, tailMB);
}
if (!pc->pcomp || protocol > 0xFF) {
c = (protocol >> 8) & 0xFF;
fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
}
c = protocol & 0xFF;
fcsOut = PPP_FCS(fcsOut, c);
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
/* Load packet. */
while (nb) {
sPtr = nBUFTOPTR(nb, u_char *);
n = nb->len;
while (n-- > 0) {
c = *sPtr++;
/* Update FCS before checking for special characters. */
fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
}
nFREE(nb, tnb);
nb = tnb;
}
/* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
/* If we failed to complete the packet, throw it away.
* Otherwise send it. */
if (!tailMB) {
st = PPPERR_ALLOC;
PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
"pppOutput[%d]: Alloc err - dropping proto=%d",
pd, protocol));
nFreeChain(headMB);
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
}
else {
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppOutput[%d]: proto=x%X %d:%.*H",
pd, protocol,
headMB->chainLen, MIN(headMB->len * 2, 50), headMB->data));
nPut(pc->fd, headMB);
#if STATS_SUPPORT > 0
pppStats.PPPopackets++;
#endif
}
headMB = NULL;
}
/* If we didn't consume the source buffer, drop it. */
if (nb)
nFreeChain(nb);
/* If we didn't send the output buffer, drop it. */
if (headMB) {
nFreeChain(headMB);
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
}
return st;
}
/* Process an nBuf chain received on given connection.
* The nBuf chain is always passed on or freed making the original
* nBuf pointer invalid. Note that this does not check for packet
* chains. This does not require complete packets but if a packet
* spans calls, those calls must be in the correct order. This is
* designed to handle packets received from the serial interface
* but could be used for a loopback interface.
* Return 0 on success, an error code on failure.
*/
int pppInput(int pd, NBuf *nb)
{
NBuf *nextNBuf;
while (nb != NULL) {
/* Consume the buffer. Ideally we could just work on the
* recieved buffer but unless we get the serial driver to
* preprocess the escape sequences, it's easier to just
* work from one buffer to another. */
pppInProc(pd, nb->data, nb->len);
nFREE(nb, nextNBuf);
nb = nextNBuf;
}
return 0;
}
/* Get and set parameters for the given connection.
* Return 0 on success, an error code on failure. */
int pppIOCtl(int pd, int cmd, void *arg)
{
PPPControl *pc = &pppControl[pd];
int st = 0;
if (pd < 0 || pd >= NUM_PPP)
st = PPPERR_PARAM;
else {
switch(cmd) {
case PPPCTLG_UPSTATUS: /* Get the PPP up status. */
if (arg)
*(int *)arg = (int)(pc->if_up);
else
st = PPPERR_PARAM;
break;
case PPPCTLS_ERRCODE: /* Set the PPP error code. */
if (arg)
pc->errCode = *(int *)arg;
else
st = PPPERR_PARAM;
break;
case PPPCTLG_ERRCODE: /* Get the PPP error code. */
if (arg)
*(int *)arg = (int)(pc->errCode);
else
st = PPPERR_PARAM;
break;
case PPPCTLG_FD:
if (arg)
*(int *)arg = (int)(pc->fd);
else
st = PPPERR_PARAM;
break;
default:
st = PPPERR_PARAM;
break;
}
}
return st;
}
/*
* Return the Maximum Transmission Unit for the given PPP connection.
*/
u_int pppMTU(int pd)
{
PPPControl *pc = &pppControl[pd];
u_int st;
/* Validate parameters. */
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag)
st = 0;
else
st = pc->mtu;
return st;
}
/*
* Write n characters to a ppp link.
* RETURN: >= 0 Number of characters written
* -1 Failed to write to device
*/
int pppWrite(int pd, const char *s, int n)
{
PPPControl *pc = &pppControl[pd];
short st = 0;
u_char c;
u_int fcsOut = PPP_INITFCS;
NBuf *headMB = NULL, *tailMB;
nGET(headMB);
if (headMB == NULL) {
st = PPPERR_ALLOC;
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
} else {
headMB->len = 0;
tailMB = headMB;
/* If the link has been idle, we'll send a fresh flag character to
* flush any noise. */
if (diffTime(pc->lastXMit) <= MAXIDLEFLAG)
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
pc->lastXMit = mtime();
/* Load output buffer. */
while (n-- > 0) {
c = *s++;
/* Update FCS before checking for special characters. */
fcsOut = PPP_FCS(fcsOut, c);
/* Copy to output buffer escaping special characters. */
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
}
/* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
c = (~fcsOut >> 8) & 0xFF;
tailMB = pppMPutC(c, &pc->outACCM, tailMB);
tailMB = pppMPutRaw(PPP_FLAG, tailMB);
/* If we failed to complete the packet, throw it away.
* Otherwise send it. */
if (tailMB) {
PPPDEBUG((pppControl[pd].traceOffset + LOG_INFO, TL_PPP,
"pppWrite[%d]: %d:%.*H",
pd,
headMB->len, MIN(headMB->len * 2, 40), headMB->data));
nPut(pc->fd, headMB);
#if STATS_SUPPORT > 0
pppStats.PPPopackets++;
#endif
}
else {
PPPDEBUG((pppControl[pd].traceOffset + LOG_WARNING, TL_PPP,
"pppWrite[%d]: Alloc err - dropping %d:%.*H",
pd,
headMB->len, MIN(headMB->len * 2, 40), headMB->data));
nFreeChain(headMB);
#if STATS_SUPPORT > 0
pppStats.PPPoerrors++;
#endif
}
}
return st;
}
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void ppp_send_config(
int unit,
int mtu,
u_int32_t asyncmap,
int pcomp,
int accomp
)
{
PPPControl *pc = &pppControl[unit];
int i;
pc->mtu = mtu;
pc->pcomp = pcomp;
pc->accomp = accomp;
/* Load the ACCM bits for the 32 control codes. */
for (i = 0; i < 32/8; i++)
pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
PPPDEBUG((LOG_INFO, TL_PPP, "ppp_send_config[%d]: outACCM=%X %X %X %X",
unit,
pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
}
/*
* ppp_set_xaccm - set the extended transmit ACCM for the interface.
*/
void ppp_set_xaccm(int unit, ext_accm *accm)
{
memcpy(pppControl[unit].outACCM, accm, sizeof(ext_accm));
PPPDEBUG((LOG_INFO, TL_PPP, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X",
unit,
pppControl[unit].outACCM[0],
pppControl[unit].outACCM[1],
pppControl[unit].outACCM[2],
pppControl[unit].outACCM[3]));
}
/*
* ppp_recv_config - configure the receive-side characteristics of
* the ppp interface.
*/
#pragma argsused /* XXX */
void ppp_recv_config(
int unit,
int mru,
u_int32_t asyncmap,
int pcomp,
int accomp
)
{
PPPControl *pc = &pppControl[unit];
int i;
/* Load the ACCM bits for the 32 control codes. */
for (i = 0; i < 32 / 8; i++)
pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
PPPDEBUG((LOG_INFO, TL_PPP, "ppp_recv_config[%d]: inACCM=%X %X %X %X",
unit,
pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
}
/*
* ccp_test - ask kernel whether a given compression method
* is acceptable for use. Returns 1 if the method and parameters
* are OK, 0 if the method is known but the parameters are not OK
* (e.g. code size should be reduced), or -1 if the method is unknown.
*/
#pragma argsused
int ccp_test(
int unit,
int opt_len,
int for_transmit,
u_char *opt_ptr
)
{
return 0; /* XXX Currently no compression. */
}
/*
* ccp_flags_set - inform kernel about the current state of CCP.
*/
#pragma argsused
void ccp_flags_set(int unit, int isopen, int isup)
{
/* XXX */
}
/*
* ccp_fatal_error - returns 1 if decompression was disabled as a
* result of an error detected after decompression of a packet,
* 0 otherwise. This is necessary because of patent nonsense.
*/
#pragma argsused
int ccp_fatal_error(int unit)
{
/* XXX */
return 0;
}
/*
* get_idle_time - return how long the link has been idle.
*/
#pragma argsused
int get_idle_time(int u, struct ppp_idle *ip)
{
/* XXX */
return 0;
}
/*
* Return user specified netmask, modified by any mask we might determine
* for address `addr' (in network byte order).
* Here we scan through the system's list of interfaces, looking for
* any non-point-to-point interfaces which might appear to be on the same
* network as `addr'. If we find any, we OR in their netmask to the
* user-specified netmask.
*/
u_int32_t GetMask(u_int32_t addr)
{
u_int32_t mask, nmask;
asm {
mov ax, WORD PTR addr
xchg ah, al
xchg ax, WORD PTR addr + 2
xchg ah, al
mov WORD PTR addr, ax
}
if (IN_CLASSA(addr)) /* determine network mask for address class */
nmask = IN_CLASSA_NET;
else if (IN_CLASSB(addr))
nmask = IN_CLASSB_NET;
else
nmask = IN_CLASSC_NET;
/* class D nets are disallowed by bad_ip_adrs */
mask = netMask | htonl(nmask);
/* XXX
* Scan through the system's network interfaces.
* Get each netmask and OR them into our mask.
*/
return mask;
}
/*
* sifvjcomp - config tcp header compression
*/
#pragma argsused
int sifvjcomp(
int pd,
int vjcomp,
int cidcomp,
int maxcid
)
{
#if VJ_SUPPORT > 0
PPPControl *pc = &pppControl[pd];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -