📄 ppp.c
字号:
case PPPCTLG_FD:
if (arg) {
*(sio_fd_t *)arg = pc->fd;
} else {
st = PPPERR_PARAM;
}
break;
#endif /* PPPOS_SUPPORT */
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;
}
#if PPPOE_SUPPORT
int
pppWriteOverEthernet(int pd, const u_char *s, int n)
{
PPPControl *pc = &pppControl[pd];
struct pbuf *pb;
/* skip address & flags */
s += 2;
n -= 2;
pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM);
if(!pb) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
return PPPERR_ALLOC;
}
pbuf_header(pb, -pppoe_hdrlen);
pc->lastXMit = sys_jiffies();
MEMCPY(pb->payload, s, n);
if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
LINK_STATS_INC(link.err);
return PPPERR_DEVICE;
}
LINK_STATS_INC(link.xmit);
return PPPERR_NONE;
}
#endif /* PPPOE_SUPPORT */
/*
* Write n characters to a ppp link.
* RETURN: >= 0 Number of characters written
* -1 Failed to write to device
*/
int
pppWrite(int pd, const u_char *s, int n)
{
PPPControl *pc = &pppControl[pd];
#if PPPOS_SUPPORT
u_char c;
u_int fcsOut;
struct pbuf *headMB, *tailMB;
#endif /* PPPOS_SUPPORT */
#if PPPOE_SUPPORT
if(pc->ethif) {
return pppWriteOverEthernet(pd, s, n);
}
#endif /* PPPOE_SUPPORT */
#if PPPOS_SUPPORT
headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
if (headMB == NULL) {
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
return PPPERR_ALLOC;
}
tailMB = headMB;
/* If the link has been idle, we'll send a fresh flag character to
* flush any noise. */
if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
}
pc->lastXMit = sys_jiffies();
fcsOut = PPP_INITFCS;
/* 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 = pppAppend(c, tailMB, &pc->outACCM);
}
/* Add FCS and trailing flag. */
c = ~fcsOut & 0xFF;
tailMB = pppAppend(c, tailMB, &pc->outACCM);
c = (~fcsOut >> 8) & 0xFF;
tailMB = pppAppend(c, tailMB, &pc->outACCM);
tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
/* If we failed to complete the packet, throw it away.
* Otherwise send it. */
if (!tailMB) {
PPPDEBUG((LOG_WARNING,
"pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
/*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
pbuf_free(headMB);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.proterr);
return PPPERR_ALLOC;
}
PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len));
/* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
nPut(pc, headMB);
#endif /* PPPOS_SUPPORT */
return PPPERR_NONE;
}
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void
ppp_send_config( int unit, int mtu, u32_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, "ppp_send_config[%d]: outACCM=%X %X %X %X\n",
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)
{
SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
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.
*/
void
ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
{
PPPControl *pc = &pppControl[unit];
int i;
LWIP_UNUSED_ARG(accomp);
LWIP_UNUSED_ARG(pcomp);
LWIP_UNUSED_ARG(mru);
/* 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, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
unit,
pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
}
#if 0
/*
* 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.
*/
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.
*/
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.
*/
int
ccp_fatal_error(int unit)
{
/* XXX */
return 0;
}
#endif
/*
* get_idle_time - return how long the link has been idle.
*/
int
get_idle_time(int u, struct ppp_idle *ip)
{
/* XXX */
LWIP_UNUSED_ARG(u);
LWIP_UNUSED_ARG(ip);
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.
*/
u32_t
GetMask(u32_t addr)
{
u32_t mask, nmask;
htonl(addr);
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 = subnetMask | 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
*/
int
sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
{
#if PPPOS_SUPPORT && VJ_SUPPORT
PPPControl *pc = &pppControl[pd];
pc->vjEnabled = vjcomp;
pc->vjComp.compressSlot = cidcomp;
pc->vjComp.maxSlotIndex = maxcid;
PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
vjcomp, cidcomp, maxcid));
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
return 0;
}
/*
* pppifNetifInit - netif init callback
*/
static err_t
pppifNetifInit(struct netif *netif)
{
netif->name[0] = 'p';
netif->name[1] = 'p';
netif->output = pppifOutput;
netif->mtu = pppMTU((int)netif->state);
return ERR_OK;
}
/*
* sifup - Config the interface up and enable IP packets to pass.
*/
int
sifup(int pd)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
netif_remove(&pc->netif);
if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
netif_set_up(&pc->netif);
pc->if_up = 1;
pc->errCode = PPPERR_NONE;
PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB) {
pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
}
} else {
st = 0;
PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
}
}
return st;
}
/*
* sifnpmode - Set the mode for handling packets for a given NP.
*/
int
sifnpmode(int u, int proto, enum NPmode mode)
{
LWIP_UNUSED_ARG(u);
LWIP_UNUSED_ARG(proto);
LWIP_UNUSED_ARG(mode);
return 0;
}
/*
* sifdown - Config the interface down and disable IP.
*/
int
sifdown(int pd)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
} else {
pc->if_up = 0;
netif_remove(&pc->netif);
PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
if(pc->linkStatusCB) {
pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
}
}
return st;
}
/**
* sifaddr - Config the interface IP addresses and netmask.
* @param pd Interface unit ???
* @param o Our IP address ???
* @param h His IP address ???
* @param m IP subnet mask ???
* @param ns1 Primary DNS
* @param ns2 Secondary DNS
*/
int
sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
}
return st;
}
/**
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
* @param pd Interface unit ???
* @param o Our IP address ???
* @param h IP broadcast address ???
*/
int
cifaddr( int pd, u32_t o, u32_t h)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
LWIP_UNUSED_ARG(o);
LWIP_UNUSED_ARG(h);
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
}
return st;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
int
sifdefaultroute(int pd, u32_t l, u32_t g)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
LWIP_UNUSED_ARG(l);
LWIP_UNUSED_ARG(g);
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(&pc->netif);
}
/* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
return st;
}
/*
* cifdefaultroute - delete a default route through the address given.
*/
int
cifdefaultroute(int pd, u32_t l, u32_t g)
{
PPPControl *pc = &pppControl[pd];
int st = 1;
LWIP_UNUSED_ARG(l);
LWIP_UNUSED_ARG(g);
if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
st = 0;
PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
} else {
netif_set_default(NULL);
}
return st;
}
/**********************************/
/*** LOCAL FUNCTION DEFINITIONS ***/
/**********************************/
#if PPPOS_SUPPORT
/* The main PPP process function. This implements the state machine according
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -