📄 ppp_ping.c
字号:
// addr1 is used to control the status LED, 0=off, 1=flash, 2=on
// returns 0 if timeout, returns 1 if wait string is matched
char sendwait(const char *send, const char *wait, unsigned int timeout) {
addr2=addr3=0;
for (TIME_SET(0); TIME<timeout; ) { // loop until time runs out
if (!addr1) P2&=0xFB; // if addr1=0 turn off status LED
else if (addr1==1) { // if addr1=1 flash status LED
if (TIME&4) P2&=0xFB; // flash period is 8 x 10ms
else P2|=4;
} else P2|=4; // if addr1>1 turn on status LED
if (serial_rx_ready()) { // is there an incoming character
P2|=1; // turn on the Rx LED
addr4 = serial_get(); // get character
//if (serial_error()) serial_fix(); // clear serial errors
if (wait[addr2]==addr4) addr2++; // does char match wait string
else addr2=0; // otherwise reset match pointer
P2&=0xFE; // turn off the Rx LED
if (!wait[addr2]) return 1; // finished if string matches
} else if (send[addr3] && (serial_tx_ready())) { // if char to send and Tx ready
if (send[addr3]=='|') { // if pause character
if (TIME>100) { // has 1 second expired yet?
TIME_SET(0); // if yes clear timer
addr3++; // and point to next character
}
} else {
P2|=2; // turn on Tx LED
TIME_SET(0); // clear timer, timeout starts after last char
serial_send(send[addr3]); // send the character
addr3++; // point to next char in tx string
}
P2&=0xFD; // turn off Tx LED
if (!send[addr3] && !(*wait))
return 1; // done if end of string and no wait string
}
}
return 0; // return with 0 to indicate timeout
}
void flash(void) { // flash all LEDs if catastrophic failure
for (TIME_SET(0);;) {
if (TIME&8) P2|=0x07; // flash period is 16 x 10ms
else P2&=0xF8;
if (TIME>3000) P2&=0xF7; // after 30 seconds turn off the power
}
}
void pulse(unsigned char dat) { // pulse Status LED with IP address
TIME_SET(0);
for(number=0;number<9;) { // pulse out 8 address bits and a blank
if (TIME<100) P2&=0xFB; // turn off Status LED between bits
else if (number<8) P2|=4; // start each address bit here
if (TIME>200 || (!(dat&0x80) && TIME>120)) { // end of bit?
TIME_SET(0); // yes, then restart timer for next bit
number++; // increment bit counter
dat<<=1; // position address to send next bit
}
}
}
// The main loop, login script, PPP state machine, and ping transponder
void main(void) {
signed int c; // serial character received
unsigned int packet = 0; // Type of the last received packet, reused as temp
unsigned char state = 0; // PPP negotiation state, from dialing=0 to done=6
unsigned char extended = 0; // flag if last character was an escape sequence
timer0_init();
serial_init(); // Initalize serial port to 2400 baud format N81
ENABLE_INT;
TIME_SET(0);
while (TIME<25); // 250 millisecond delay to prevent false power up
P2=8; // Turn on the power so user can release power button
for(number=1;;number++) { // Redial indefinately every 30 seconds
if (number==10) P2&=0xF7; // Turn off power if dialing fails
addr1=0; // Set flag to keep the Status LED off
if(!sendwait("|+++|\rath\r|atz\r|at&fs11=55\r|atdt","atdt",3000)) // Init modem
flash();
addr1=1; // Set flag to flash Status LED
// Modify this line with your ISP phone number
//if (sendwait("5551234\r","NNECT",3000)) {
// I changed to direct connection under windows
if (sendwait("CLIENT","CLIENTSERVER",3000)) {
addr1=2; // Set flag to keep the Status LED on
//if (sendwait("",": ",1000)) { // Wait for user id prompt
// if (sendwait("userid\r","word:",200)) // Modify these lines as described
// if (sendwait("password\r","tion:",1000))
// if (!sendwait("ppp\r","IP address",200))
// // Modify is start PPP command is not ppp or 2
// sendwait("2\r","IP address",200);
//}
//else {
if (sendwait("\x7e\xff\x7d\x23\x08\x08\x08\x08","~~",1000))
break; // Start PPP
else
flash();
//}
}
}
// State machine loop until successful ping or PPP negotiation timeout
for (TIME_SET(0);;) {
if (TIME>7000 || number>20) P2&=0xF7;
if (serial_rx_ready()) { // Incoming character?
P2 ^=1; // Turn on Rx LED
c = serial_get(); // get the character
//if (serial_error()) serial_fix(); // clear Rx errors
if (c == 0x7E) { // start or end of a packet
if (rx_ptr && (checksum1==0xF0B8))
packet = rx_str[2]*256 + rx_str[3]; // if CRC passes accept packet
extended &= 0x7E; // clear escape character flag
rx_ptr = 0; // get ready for next packet
checksum1 = 0xFFFF; // start new checksum
} else if (c == 0x7D) { // if tilde character set escape flag
extended |= 1;
} else {
if (extended&1) { // if escape flag
c ^= 0x20; // recover next character
extended &= 0xFE; // clear Rx escape flag
}
if (rx_ptr==0 && c!=0xff) rx_str[rx_ptr++] = 0xff; // uncompress PPP header
if (rx_ptr==1 && c!=3) rx_str[rx_ptr++] = 3;
if (rx_ptr==2 && (c&1)) rx_str[rx_ptr++] = 0;
rx_str[rx_ptr++] = c; // insert character in buffer
if (rx_ptr>MaxRx) rx_ptr = MaxRx; // Inc pointer up to end of buffer
checksum1 = calc(c^checksum1) ^ (checksum1/256); // calculate CRC checksum
}
P2&=0xFE; // turn off Status LED
} else if (tx_end && (serial_tx_ready())) { // Data to send and Tx empty?
P2|=2; // turn on Tx LED
c = tx_str[tx_ptr]; // get character from buffer
if (tx_ptr==tx_end) { // was it the last character
tx_end=0; // mark buffer empty
c='~'; // send tilde character last
P2&=0xFD; // turn off Tx LED
} else if (extended&2) { // sending escape sequence?
c^=0x20; // yes then convert character
extended &= 0xFD; // clear Tx escape flag
tx_ptr++; // point to next char
} else if (c<0x20 || c==0x7D || c==0x7E) { // if escape sequence required?
extended |= 2; // set Tx escape flag
c = 0x7D; // send escape character
} else {
if (!tx_ptr) c='~'; // send ~ if first character of packet
tx_ptr++;
}
serial_send(c); // Put character in transmitter
}
if (packet == LCP) {
switch (rx_str[4]) { // Switch on packet type
case REQ:
state &= 0xfd; // clear remote ready state bit
if (c=TestOptions(0x00c6)) { // is option request list OK?
if (c>1) {
c = ACK; // ACK packet
if (state<3) state |= 2; // set remote ready state bit
} else {
rx_str[10]=0xc0; // else NAK password authentication
c = NAK;
}
} else { // else REJ bad options
c = REJ;
}
TIME_SET(0);
MakePacket(LCP,c,rx_str[5],rx_str+7); // create LCP packet from Rx buffer
break;
case ACK:
if (rx_str[5]!=number) break; // does reply id match the rrquest
if (state<3) state |= 1; // Set the local ready flag
break;
case NAK:
state &= 0xfe; // Clear the local ready flag
break;
case REJ:
state &= 0xfe; // Clear the local ready flag
break;
case TERM:
break;
}
if (state==3) state = 4; // When both ends ready, go to state 4
} else if (packet == PAP) {
switch (rx_str[4]) { // Switch on packet type
case REQ:
break; // Ignore incoming PAP REQ
case ACK:
state = 5; // PAP ack means this state is done
break;
case NAK:
break; // Ignore incoming PAP NAK
}
} else if (packet == IPCP) {
switch (rx_str[4]) { // Switch on packet type
case REQ:
if (TestOptions(0x0004)) { // move to next state on ACK
c = ACK;
state = 6;
} else { // otherwise reject bad options
c = REJ;
}
MakePacket(IPCP,c,rx_str[5],rx_str+7);
break; // Create IPCP packet from Rx buffer
case ACK:
if (rx_str[5]==number) { // If IPCP response id matches request id
state = 7; // Move into final state
pulse(addr1); // Pulse Status LED to show the
pulse(addr2); // IP address
pulse(addr3);
pulse(addr4);
P2|=4; // Turn on Status LED after pulsing
TIME_SET(5800); // Move timer ahead for quicker PING
}
break;
case NAK: // This is where we get our address
addr1 = rx_str[10];
addr2 = rx_str[11]; // Store address for use in IP packets
addr3 = rx_str[12];
addr4 = rx_str[13];
MakePacket(IPCP,REQ,rx_str[5],rx_str+7);
break; // Make IPCP packet from Rx buffer
case REJ:
break; // Ignore incoming IPCP REJ
case TERM:
break; // Ignore incoming IPCP TERM
}
} else if (packet == IP) {
if (state<7 || (rx_str[19]==addr4 && rx_str[18]==addr3 &&
rx_str[17]==addr2 && rx_str[16]==addr1)) {
// ignore echoed packets from our address or before we reach state 7
// may power down here because echos are good indications that modem
// connection hungup
// This would be a good place to insert a traceroute test and
// response
} else if (rx_str[13]==1) { // IP packet with ICMP payload
if (rx_str[24]==8) { // Received PING request
rx_str[20]=rx_str[16]; // Copy 4 origin address bytes to
// destination address
rx_str[21]=rx_str[17];
rx_str[22]=rx_str[18];
rx_str[23]=rx_str[19];
rx_str[19]=16; // Length of IP address(4) + ping protocol(8) + 4
rx_str[24]=0; // Change received ping request(8) to ping reply(0)
packet = rx_str[28]+rx_str[30]; // Calculate 1's comp checksum
rx_str[26] = packet&255;
rx_str[27] = packet/256;
packet = rx_str[27]+rx_str[29]+rx_str[31];
rx_str[27] = packet&255;
packet = packet/256 + rx_str[26];
rx_str[26] = packet&255;
rx_str[27] += packet/256;
rx_str[26] = ~rx_str[26]; // Invert the checksum bits
rx_str[27] = ~rx_str[27];
MakePacket(IP,0,1,rx_str+19); // Make IP packet from modified Rx buffer
} else if (rx_str[24]==0) { // Received PING reply
if ((rx_str[28]|rx_str[30]|rx_str[31])+rx_str[29]==1) {
P2&=0xF7; // Turn off the power after successful ping
}
}
}
} else if (packet == CCP) {
switch (rx_str[4]) { // If CCP response id matches request id
case REQ:
c = REJ;
if (TestOptions(0x0004)) c = ACK; // ACK option 3 only, REJ anything else
MakePacket(CCP,c,rx_str[5],rx_str+7); // Create CCP ACK or REJ packet
// from Rx buffer
}
} else if (packet) { // Ignore any other received packet types
} else if (!tx_end && (state==0 || state==2) && TIME>100) {
// Once a second try negotiating LCP
number++; // Increment Id to make packets unique
TIME_SET(0); // Reset timer
MakePacket(LCP,REQ,number,"\x0E\x02\x06\x00\x0A\x00\x00\x07\x02\x08\x02");
// Reqest LCP options 2,7,8
} else if (!tx_end && state == 4 && TIME>100) {
// Once a second try negotiating password
TIME_SET(0); // Reset timer
number++;
// format like printf("%c%c%s%c%s",strlen(name)+strlen(password)+6,
//strlen(name),name,strlen(password),password);
// Modify this line as described above
MakePacket(PAP,REQ,number,"\x14\x06userid\x08password");
} else if (!tx_end && state == 6 && TIME>100) {
// Once a second try negotiating IPCP
number++; // Increment Id to make packets unique
TIME_SET(0); // Reset timer
MakePacket(IPCP,REQ,number,"\xA\x3\x6\x0\x0\x0\x0");
// Request IPCP option 3 with addr 0.0.0.0
} else if (!tx_end && state == 7 && TIME>3000) { // Every 30 seconds do a ping
TIME_SET(0); // Reset timer
number++; // Increment ping count
MakePacket(IP,0,1,"\x10\xCF\xA1\x75\x43\x8\x0\xF7\xFE\x0\x1\x0\x0");
// Ping 207.161.117.67
}
packet = 0; // Indicate that packet is processed
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -