📄 ifppp.c
字号:
return (0); /* OK return - this is not an error */
}
}
/* Insert PPP_IP type at front of IP packet */
pkt->nb_prot -= 2; /* space for PPP_IP header */
if (pkt->nb_prot < pkt->nb_buff)
{
dtrap("ifppp 5\n"); /* there should always be room to prepend MAC header */
panic("ppp_pkt_output: no MAC prepend space");
}
pkt->nb_plen += 2; /* for PPP_IP header */
/* build PPP_IP header at pkt->nb_prot */
ppp_putshort((u_char*)pkt->nb_prot, PPP_IP);
/* see if we need to start the PPP link for IPCP: */
if(mppp->states[IPCP_STATE] != ST_OPENED)
ppp_open(mppp, IPCP_STATE);
/* lastly, add the packet to the send queue and spin send logic */
#ifdef PPP_MULTILINK
/* see if we need to fragment the packet over a multilink bundle */
if((mppp->ml_numlinks > 1) && /* does this bundle have multiple links. */
(pkt->nb_plen > mppp->ml_frag_size)) /* and packet is big? */
{
err = pppml_sendpkt(mppp, pkt); /* hand over to ML code */
return err;
}
#endif /* PPP_MULTILINK */
putq(&mppp->dataq, (qp)pkt); /* add to data packet send queue */
/* spin the dataq send logic */
err = ppp_allpktsend(mppp);
return err;
}
/* FUNCTION: ppp_ifclose()
*
* net iface close routine, called from netclose. A full graceful
* PPP shutdown is probably optimistic, so it just tries to disconnect
* the line device. This should eventually trigger the FSM shutdown events.
*
* PARAM1: int iface
*
* RETURNS:
*/
int
ppp_ifclose(int iface)
{
M_PPP mppp;
mppp = (M_PPP)nets[iface]->n_local;
if(mppp && (mppp->line.ln_state == LN_CONNECTED))
mppp->line.ln_disconnect(&mppp->line);
return 0;
}
/* FUNCTION: ppp_mstats()
*
* PPP link statistics routine. This called from the MAC stats routine below
* as well as from pppmenu.c
*
* PARAM1: void * pio
* PARAM2: M_PPP mppp
*
* RETURNS: void
*/
#ifndef NO_CONPRINTF
extern char * fsmstate[]; /* strings for state names */
#endif
void
ppp_mstats(void * pio, M_PPP mppp)
{
ns_printf(pio, "PPP stats for link %lx:\n", mppp);
#ifndef NO_CONPRINTF
ns_printf(pio, "states: LCP:%s, IPCP:%s \n",
fsmstate[mppp->states[LCP_STATE]],
fsmstate[mppp->states[IPCP_STATE]]);
#else
ns_printf(pio, "states: LCP:%u, IPCP:%u \n",
mppp->state[LCP_STATE],
mppp->state[IPCP_STATE]);
#endif
ns_printf(pio, "pkts (bytes); in:%lu(%lu), out:%lu(%lu)\n",
mppp->pkts_in, mppp->bytes_in, mppp->pkts_out, mppp->bytes_out);
ns_printf(pio, "flags; PPP:%04x, SC:%04x; errors: fsm:%d, io:%d\n",
mppp->pppflags, mppp->sc_flags, mppp->bad_fcs, mppp->io_errors);
ns_printf(pio, "output queues (max,current): ctrl(%u,%u), data(%u,%u)\n",
mppp->fastq.q_max, mppp->fastq.q_len,
mppp->dataq.q_max, mppp->dataq.q_len);
ns_printf(pio, "timers set:%d cleared:%d fired:%d replaced:%d\n",
mppp->tmr_sets, mppp->tmr_cleared, mppp->tmr_fired, mppp->tmr_replaced);
ns_printf(pio, "asynmaps; ours: %lx, his:%lx \n",
mppp->my_asyncmap, mppp->his_asyncmap);
ns_printf(pio, "MRUs; ours: %d, his:%d \n",
mppp->lcp_gotoptions.mru, mppp->lcp_hisoptions.mru);
ns_printf(pio, "Negotiated Auth; his: CHAP:%s PAP:%s ours: CHAP:%s PAP:%s\n",
mppp->lcp_hisoptions.neg_chap?"YES":"NO",
mppp->lcp_hisoptions.neg_upap?"YES":"NO",
mppp->lcp_gotoptions.neg_chap?"YES":"NO",
mppp->lcp_gotoptions.neg_upap?"YES":"NO");
ns_printf(pio, "Negotiated VJ: us:%s him:%s\n",
(mppp->sc_flags & SC_COMP_TCP)?"YES":"NO",
(mppp->ipcp_gotoptions.neg_vj)?"YES":"NO");
#ifdef PPP_IDENTIFY
if(mppp->identity[0] != 0)
ns_printf(pio, "His Identity: %s\n", mppp->identity);
#endif /* PPP_IDENTIFY */
#ifndef SL_NO_STATS
#ifdef PPP_VJC
ns_printf(pio, "VJ send stats; pkts %ld, comp. %ld, searches %ld, misses %ld\n",
mppp->sc_comp.sls_packets,
mppp->sc_comp.sls_compressed,
mppp->sc_comp.sls_searches,
mppp->sc_comp.sls_misses);
ns_printf(pio, "VJ recv stats; uncomp. %ld, comp. %ld, err %ld, tossed %ld\n",
mppp->sc_comp.sls_uncompressedin,
mppp->sc_comp.sls_compressedin,
mppp->sc_comp.sls_errorin,
mppp->sc_comp.sls_tossed);
#endif /* PPP_VJC */
#endif /* not SL_NO_STATS */
#ifdef PPP_MULTILINK
if(mppp->pppflags & ML_IPCP) /* bundle master? */
{
int i;
ns_printf(pio, "ML bundle type %d, data:", mppp->ml_conf.endp_class);
for(i = 0; i < mppp->ml_conf.endp_length; i++)
ns_printf(pio, "%02X ", mppp->ml_conf.endp_desc[i] );
ns_printf(pio, "\n");
}
ns_printf(pio, "ML frag thresh:%d; sent:%lu rcvd:%lu err:%lu drop:%lu tmo:%lu\n",
mppp->ml_frag_size, mppp->mf_txfrags, mppp->mf_rxfrags,
mppp->mf_errors, mppp->mf_drops, mppp->mf_tmo);
#endif /* PPP_MULTILINK */
switch (mppp->line.lower_type)
{
#ifdef USE_PPPOE
case LN_PPPOE:
poe_stats(pio, mppp);
break;
#endif /* USE_PPPOE */
#ifdef USE_MODEM
case LN_ATMODEM:
/* modem code currently only supports stats for first unit */
if(mppp->line.lower_unit == 0)
dialer_status(pio);
else
ns_printf(pio, "Modem unit %d\n", mppp->line.lower_unit);
break;
#endif /* USE_MODEM */
#ifdef USE_COMPORT
case LN_UART:
uart_stats(pio, mppp->line.lower_unit);
break;
#endif /* USE_COMPORT */
#ifdef LB_XOVER
case LN_LBXOVER:
ns_printf(pio, "type %d, loopback-crosover\n");
break;
#endif /* LB_XOVER */
default:
ns_printf(pio, "unknown type: %d\n", mppp->line.lower_type);
break;
}
}
/* FUNCTION: ppp_stats()
*
* Entry point for the MAC driver stats routine. This just extracts the
* mppp object and calls the mppp-ish stats routine
*
* PARAM1: void * pio
* PARAM2: int iface
*
* RETURNS:
*/
void
ppp_stats(void * pio, int iface)
{
M_PPP mppp;
mppp = (M_PPP)nets[iface]->n_local;
ppp_mstats(pio, mppp);
}
/* FUNCTION: ppp_pktdemux()
*
* Handle received PPP packets.
*
* PARAM1: none
*
* RETURNS: void
*/
/* Only needed IF we are using packet oriented PPP links in this build */
#ifdef PPP_PACKETS
void
ppp_pktdemux()
{
PACKET pkt;
M_PPP mppp;
while(ppp_rcvdq.q_len)
{
pkt = (PACKET)getq(&ppp_rcvdq);
#ifdef PPP_MULTILINK
/* for multilink we have to get exactly to right link, not just the
* right interface
*/
mppp = (M_PPP)(pkt->link);
#else
/* non-multilink ports have only one link per iface */
mppp = (M_PPP)(pkt->net->n_local);
#endif
#ifdef NPDEBUG
if(mppp->ifp != pkt->net)
panic("ppp demux");
#endif
ppp_inpkt(mppp, pkt);
}
}
#endif /* PPP_PACKETS */
static int pt_reentry = 0;
/* FUNCTION: ppp_timeisup()
*
* PPP periodic timer, called from misclib/timeouts.c and used to
* drive timeouts of various sorts.
*
* PARAM1: none
*
* RETURNS: void
*/
void
ppp_timeisup(void)
{
M_PPP mppp;
if (pt_reentry) /* this happens a lot on slow DOS devices */
return; /* prevent re-entry of this routine */
pt_reentry++;
/* loop through the sessions and see if it's time for a retry */
for(mppp = ppp_list; mppp; mppp = mppp->next)
{
if((mppp->tmo_tick != 0) &&
(mppp->tmo_tick <= cticks))
{
//ConPrintf("ppp timeout (link %p), trys left: %d\n",
//mppp, mppp->retrys);
mppp->tmo_tick = 0; /* clear timer */
mppp->tmr_fired++;
mppp->tmo_func(mppp, (long)(mppp->tmo_parm) );
}
/* also see if we can start a delayed send */
if(((mppp->dataq.q_len) || (mppp->fastq.q_len)) &&
((mppp->pppflags & PPP_SENDING) == 0))
{
ppp_allpktsend(mppp);
}
#ifdef PPP_MULTILINK
/* see if a multilink fragment reassembly has timed out. Limit
* this test to multilink units which currently actually have
* multiple links.
*/
if(mppp->ml_numlinks > 1)
{
int i;
for(i = 0; i < MAX_ML_FRAGS; i++) /* loop thru reasm list */
{
if(mppp->reasms[i].pkt == NULL) /* no entry */
continue;
if(mppp->reasms[i].tmo <= cticks) /* check RU time */
{
pppml_delfrag(&mppp->reasms[i]); /* clear reasmbly info */
mppp->mf_tmo++;
}
}
}
#endif /* PPP_MULTILINK */
}
#ifdef USE_PPPOE
poe_check(); /* PPPOE needs a timer too */
#endif
#ifdef PPP_PACKETS
ppp_pktdemux();
#endif /* PPP_PACKETS */
pt_reentry--;
}
/* FUNCTION: ppp_settimer()
*
* Set timer to call func() in count number of seconds.
*
* PARAM1: mppp - ppp link for timer
* PARAM2: void (*func)(M_PPP, long) - routine to call on expiry
* PARAM3: int seconds - timer value
* PARAM4: long arg - arg to func() callback
*
* RETURNS: void
*/
void
ppp_settimer(M_PPP mppp, void (*func)(M_PPP, long), int secs, long arg)
{
/* count times we over-write a running timer with a new one */
if(mppp->tmo_tick != 0)
mppp->tmr_replaced++;
ENTER_CRIT_SECTION(mppp); /* keep it from firing while we set up */
mppp->tmo_tick = cticks + (secs * (u_long)TPS);
mppp->tmo_parm = arg;
mppp->tmo_func = func;
mppp->tmr_sets++;
EXIT_CRIT_SECTION(mppp);
}
/* FUNCTION: ppp_cleartimer()
*
* Clear a mppp timer.
*
* PARAM1: mppp - ppp link
*
* RETURNS:
*/
void
ppp_cleartimer(M_PPP mppp)
{
if(mppp->tmo_tick)
{
mppp->tmr_cleared++;
mppp->tmo_tick = 0;
}
}
#if defined(CHAP_SUPPORT) || defined(PAP_SUPPORT)
/* FUNCTION: ppp_auth_failed()
*
* called if CHAP or PAP authorization fails
*
* PARAM1: M_PPP mppp
* PARAM2: int who - 0 == we failed, 1 == peer failed
*
* RETURNS: void
*/
void
ppp_auth_failed(M_PPP mppp, int who)
{
/* put this on both the console and the log */
dprintf("link %p Auth FAILURE: %s failed authentication\n", mppp,
who?"peer":"we");
//ConPrintf("link %p Auth FAILURE: %s failed authentication\n", mppp,
//who?"peer":"we");
ppp_close(mppp, LCP_STATE); /* kill LCP layer */
}
#endif /* defined(CHAP_SUPPORT) || defined(PAP_SUPPORT) */
/* FUNCTION: ppp_set_ipaddr()
*
* Check the IP address field in the outgoing packet. It
* it is all zeros,then insert our IP Address.
*
* This is needed in the case when ppp_pkt_output() is called, the
* link is not connected, and has no assigned IP address. In this case
* ppp_pkt_output() queues the packet until an IP address is assigned
* either via IPCP or DHCP. The queued packet has a source IP address
* of zero, which won't get it very far, so this routine patches
* up the packet with the correct IP address.
*
* PARAM1: PACKET pkt
*
* RETURNS: void
*/
extern u_short tcp_cksum(struct ip *);
#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6
#endif
void
ppp_set_ipaddr(PACKET pkt)
{
struct ip * pip;
/* struct tcphdr * tcpp; */
/* Assign our new IP address and update the IPHEADER_CHECKSUM */
/* Assign only if the SRC IP address in original packet is zero */
/* IP header follows 2 bytes of PPP header */
pip = (struct ip*)(pkt->nb_prot + 2);
if ( pip->ip_src == 0 )
{
//ConPrintf("Updating Src IP\n");
pip->ip_src = pkt->net->n_ipaddr;
pip->ip_chksum = IPXSUM; /* clear checksum field for summing */
pip->ip_chksum = ~cksum(pip, 10);
}
else /* address was already set */
return;
/* If it's a TCP packet, we need to adjust the TCP checksum too */
if (pip->ip_prot == IPPROTO_TCP)
{
struct tcphdr * tcpp; /* tcp header */
unsigned hlen = (pip->ip_ver_ihl & 0x0F); /* length of IP header */
unsigned long deltasum; /* checksum workspace */
int loops = 0;
hlen <<= 2; /* convert length of iP header to bytes */
tcpp = (struct tcphdr *)((char*)pip+hlen);
deltasum = (u_short)~(tcpp->th_sum);
deltasum += (u_short)(pip->ip_src & 0x0000FFFF);
deltasum += (u_short)(pip->ip_src >> 16);
while (deltasum & 0xFFFF0000) /* carry bits need to be wrapped? */
{
hlen = (unsigned)(deltasum >> 16); /* get # carry bits */
deltasum &= 0x0000FFFF; /* clear carry bits in sum */
deltasum += hlen; /* add carry bits back in */
if (loops++ > 2) /* should never loop more than twice */
{
dtrap("ifppp 6\n");
break; /* send packet anyway, TCP will probably retry */
}
}
tcpp->th_sum = ~((u_short)deltasum);
#ifdef NPDEBUG /* doublecheck sum if debugging, omit test later -JB- */
if (tcpp->th_sum != tcp_cksum(pip))
{
dprintf("inser_ip_addr: delta cksum bug, was:%x good:%x \n",
tcpp->th_sum, tcp_cksum(pip));
}
#endif
}
else if(pip->ip_prot == UDP_PROT)
{
/* Adjust the UDP check sum */
struct udp * pup;
struct ph php;
unsigned hlen = (pip->ip_ver_ihl & 0x0F); /* length of IP header */
hlen <<= 2; /* convert length of iP header to bytes */
pup = (struct udp*)((char*)pip+hlen);
#ifdef NO_UDP_CKSUM
pup->ud_cksum = 0;
#else
php.ph_src = pip->ip_src;
php.ph_dest = pip->ip_dest;
php.ph_zero = 0;
php.ph_prot = UDP_PROT;
php.ph_len = pup->ud_len;
pup->ud_cksum = cksum(&php, sizeof(struct ph)>>1);
pup->ud_cksum = ~cksum(pup, (htons(pup->ud_len)+1)>>1);
#endif
}
}
#endif /* USE_PPP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -