📄 ip.c
字号:
//
for (i = 0; ; i++)
{
rmemcpy((char*)&dw1, AllowedIP[i], 4); //
if (!dw1) break; // end of list
if (IP_Header->SourceIP.ip32 == dw1) return false; // allow it
}
// rmemcpy((char*)&dw1, SubnetMask, 4); //
// dw2 = IP_Header->SourceIP.ip32 & dw1; //
// dw1 &= PPP.OUR_IP.ip32; //
// if (dw1 != dw2) return true; // different subnet - firewall it
// return false; // let it thru
return true; // firewall it
}
// **************************************************************************
// Calculate a checksum - used in IP packets
u32 IP_Checksum(char *p, u16 len)
{ // this one REALLY needs to be as fast as possible - best to do this in assembler code
register u16 i;
register u32 checksum = 0;
register u16 *q;
if (!p) return 0;
if (len == 0) return 0;
q = (u16*)p;
for (i = 0; i < (len >> 1); i++) checksum += (u32)ntohs(*q++);
if (len & 1) checksum += (u32)(ntohs(*q) & 0xff00);
return checksum;
}
u16 IP_ChecksumFinalize(u32 checksum)
{
checksum = (checksum & 0x0000ffff) + ((checksum >> 16) & 0x0000ffff);
if (checksum & 0xffff0000) checksum++;
checksum = ~checksum;
return (u16)(checksum & 0x0000ffff);
}
u16 IP_Checksum1(char *p, u16 len)
{
u32 checksum = IP_Checksum(p, len);
return IP_ChecksumFinalize(checksum);
}
u16 IP_Checksum2(char *p, u16 len)
{
u16 w;
u32 checksum;
// the tcp and udp packet checksums needs a pseudo header bringing into the calculation.
// the header is not sent with the packet though, it's just for checksum calc.
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Source address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Destination address |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | zero | Protocol | UDP/TCP Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
checksum = IP_Checksum(p, len); // checksum the packet
//
checksum += IP_Checksum((char*)&IP_Header->SourceIP.ip32, 4); // now pull in the pseudo header
checksum += IP_Checksum((char*)&IP_Header->DestIP.ip32, 4); //
w = htons(IP_Header->Protocol); checksum += IP_Checksum((char*)&w, 2); //
w = htons(len); checksum += IP_Checksum((char*)&w, 2); //
//
return IP_ChecksumFinalize(checksum); // return the final checksum value
}
// **************************************************************************
void IP_dec(void)
{
// IP packet
// RFC 791
// http://www.freesoft.org/CIE/Course/Section3/
u8 type, len;
u16 w;
IP_Header = (T_IP_Header*)(MainBuffer + MainBufferRd_Rx); // point to the IP header
//
w = MainBufferWr_Rx - MainBufferRd_Rx; // number of bytes we have
if (w < sizeof(T_IP_Header)) return; // we don't have enough bytes for the ip header - drop the packet
//
if ((IP_Header->VerLen & 0xf0) != 0x40) return; // drop the packet as we're only programmed to deal with IP V4
//
w = (IP_Header->VerLen & 0x0f) << 2; // i = length of header in bytes
if (w < sizeof(T_IP_Header)) return; // error
if (MainBufferWr_Rx < (MainBufferRd_Rx + w)) return; // we still don't have enough bytes for the ip header - drop the packet
//
if ((!IP_Header->Checksum) || (IP_Checksum1((char *)IP_Header, w))) //
{ // invalid checksum
#ifdef Debug //
SendDebugRStr(ip_str16); //
#endif //
return; //
} //
//
w = ntohs(IP_Header->TotalLength); // total packet length
if (MainBufferWr_Rx < (MainBufferRd_Rx + w)) return; // we still don't have enough bytes for the ip header - drop the packet
MainBufferWr_Rx = MainBufferRd_Rx + w; // just incase they have padded the packet out - this will drop the padding
//
if (IP_Header->SourceIP.ip32 == PPP.OUR_IP.ip32) return; // ahmmmmm, we sent this packet - must be in loop-back mode - drop it
// ********************************
#ifdef Debug
IP_DisplayProtocol(false, MainBufferWr_Rx);
IP_DisplayHeader(MainBufferRd_Rx, MainBufferWr_Rx);
#endif
// ********************************
w = (u16)(IP_Header->VerLen & 0x0f) << 2; // w = length of header in bytes
w += MainBufferRd_Rx; // point to data (immediately follows the IP header)
MainBufferRd_Rx += sizeof(T_IP_Header); // point to header options
while (MainBufferRd_Rx < w) //
{ // go thru each IP header option
type = MainBuffer[MainBufferRd_Rx++]; // option type
len = 0; //
if (!type) break; // end of option list
if (type == 1) continue; // no length byte (NOP option)
len = MainBuffer[MainBufferRd_Rx++]; // option length
if (len < 2) len = 2; //
//
//
MainBufferRd_Rx += (len - 2); //
} //
MainBufferRd_Rx = w; // point to IP data
// ********************************
if ((IP_Header->DestIP.ip32 != 0xffffffff) && (IP_Header->DestIP.ip32 != PPP.OUR_IP.ip32)) return; // it's not for us so drop it now
// ********************************
// check for fragmentation
w = ntohs(IP_Header->Fragment); //
//
if (w & IP_FRAGMENTED) //
{ //
#ifdef Debug
SendDebugRStr(ip_str17); //
#endif
return; // we don't yet deal with fragmentation - just not got the ram available :(
} // .. but how do we force the other end to set the "don't fragment" flag when sending packets ?
//
// w &= IP_FRAGMENT_OFFSET; // w = fragment offset
// ********************************
#ifdef IncludeICMP
if (IP_Header->Protocol == IP_PROTO_ICMP) ICMP_In(); //
#endif
#ifdef IncludeUDP
else //
if (IP_Header->Protocol == IP_PROTO_UDP) UDP_In(); //
#endif
#ifdef IncludeTCP
else //
if (IP_Header->Protocol == IP_PROTO_TCP) TCP_In(); //
#endif
// ********************************
}
// **************************************************************************
// start an IP packet
void IP_StartPacket(u8 Protocol, u32 IP)
{
PPP_StartPacket(PPP_IP); //
//
IP_Header = (T_IP_Header*)(MainBuffer + MainBufferWr_Tx); // point to the IP header
memset(IP_Header, 0, sizeof(T_IP_Header)); // clear it
//
IP_Header->VerLen = 0x40 | (sizeof(T_IP_Header) >> 2); //
IP_Header->TOS = 0x04; // make it high-reliable
// IP_Header->TOS = 0x08; // make it high-throughput - suseptable to retires though
IP_Header->TotalLength = sizeof(T_IP_Header); //
IP_Header->ID = IP_ID++; //
IP_Header->Fragment = IP_DONT_FRAGMENT; //
IP_Header->TTL = 128; //
IP_Header->Protocol = Protocol; //
IP_Header->SourceIP.ip32 = PPP.OUR_IP.ip32; //
IP_Header->DestIP.ip32 = IP; //
//
MainBufferWr_Tx += sizeof(T_IP_Header); // update index
}
void IP_EndPacket(void)
{
u16 w; //
//
IP_Header->ID = htons(IP_Header->ID); //
IP_Header->Fragment = htons(IP_Header->Fragment); //
IP_Header->TotalLength = htons(IP_Header->TotalLength); //
//
w = (u16)(IP_Header->VerLen & 0x0f); // number of 32-bit words to the ip header
w <<= 2; // now number of bytes
w = IP_Checksum1((char*)IP_Header, w); // update the IP header checksum
// if (!w) w = 0xffff; //
IP_Header->Checksum = htons(w); //
}
// **************************************************************************
// this is called from the ppp module - every 10ms
void IP_10ms_Timer(void)
{
#ifdef IncludeICMP
ICMP_10ms_Timer(); //
#endif
#ifdef IncludeUDP
UDP_10ms_Timer(); //
#endif
#ifdef IncludeTCP
TCP_10ms_Timer(); //
#endif
}
// **************************************************************************
// this is called from the ppp module - as often as pos
void IP_Process(void)
{
#ifdef IncludeTCP
TCP_Process(); //
#endif
}
// **************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -