📄 ip.c
字号:
return(-2);
/* Select network buffer */
/* TODO: This network related stuff should */
/* be moved and abstracted to Ethernet layer */
switch(pcol) {
case IP_ICMP:
NETWORK_SEND_INITIALIZE(ICMP_BUF);
IP_DEBUGOUT("Assembling IP packet to ICMP buffer\n\r");
break;
case IP_UDP:
NETWORK_SEND_INITIALIZE(UDP_BUF);
IP_DEBUGOUT("Assembling IP packet to UDP buffer\n\r");
break;
case IP_TCP:
NETWORK_SEND_INITIALIZE(TCP_BUF);
IP_DEBUGOUT("Assembling IP packet to TCP buffer\n\r");
break;
default: /* Unknown protocol */
return(-1);
}
/* Fill the Ethernet information */
for( i=0; i<MAXHWALEN; i++) {
send_frame.destination[i] = qstruct->hwadr[i];
send_frame.source[i] = localmachine.localHW[i];
}
send_frame.protocol = PROTOCOL_IP;
#pragma MESSAGE DISABLE C1825 //Warning: indirection
NETWORK_ADD_DATALINK(&send_frame);
#pragma MESSAGE WARNING C1825 //Warning: indirection
/* Construct the IP header */
send_ip_packet.vihl = IP_DEF_VIHL;
send_ip_packet.tos = tos;
send_ip_packet.tlen = IP_HLEN + len;
send_ip_packet.id = ip_id++;
send_ip_packet.frags = 0;
send_ip_packet.ttl = ttl;
send_ip_packet.protocol = pcol;
send_ip_packet.checksum = 0;
send_ip_packet.sip = localmachine.localip;
send_ip_packet.dip = ipadr;
/* Calculate checksum for the IP header */
send_ip_packet.checksum = (UINT16)(ip_construct_cs( &send_ip_packet ));
/* Assemble bytes to network */
SEND_NETWORK_B(send_ip_packet.vihl);
SEND_NETWORK_B(send_ip_packet.tos);
SEND_NETWORK_W( send_ip_packet.tlen );
SEND_NETWORK_W( send_ip_packet.id );
SEND_NETWORK_W( send_ip_packet.frags );
SEND_NETWORK_B(send_ip_packet.ttl);
SEND_NETWORK_B(send_ip_packet.protocol);
SEND_NETWORK_W( send_ip_packet.checksum );
SEND_NETWORK_B( (UINT8)(send_ip_packet.sip >> 24) );
SEND_NETWORK_B( (UINT8)(send_ip_packet.sip >> 16) );
SEND_NETWORK_B( (UINT8)(send_ip_packet.sip >> 8) );
SEND_NETWORK_B( (UINT8) send_ip_packet.sip );
SEND_NETWORK_B( (UINT8)(send_ip_packet.dip >> 24) );
SEND_NETWORK_B( (UINT8)(send_ip_packet.dip >> 16) );
SEND_NETWORK_B( (UINT8)(send_ip_packet.dip >> 8) );
SEND_NETWORK_B( (UINT8) send_ip_packet.dip );
/* Assemble data */
SEND_NETWORK_BUF(dat,len);
/* Launch it */
NETWORK_COMPLETE_SEND( send_ip_packet.tlen );
return(len);
}
/** \brief Construct checksum of the IP header
* \author
* \li Jari Lahti
* \date 08.07.2002
* \param frame pointer to ip_frame structure holding header information
* based on which checksum is calculated
* \return Calculated checksum
*
* Checksum of the supplied IP datagram is calculated.
*
*/
UINT32 ip_construct_cs (struct ip_frame* frame)
{
UINT16 ip_cs;
UINT8 cs_cnt;
UINT8 olen;
UINT8 i;
ip_cs = 0;
cs_cnt = 0;
ip_cs = ip_checksum(ip_cs, frame->vihl, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->tos, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->tlen >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->tlen, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->id >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->id, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->frags >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->frags, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->ttl, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->protocol, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 24), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 16), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->sip, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 24), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 16), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->dip, cs_cnt++);
/* Is there options? */
olen = ((frame->vihl & 0x0F) << 2) - IP_MIN_HLEN;
for( i=0; i<olen; i++)
ip_cs = ip_checksum(ip_cs, (UINT8)frame->opt[i], cs_cnt++);
/* Take complement */
ip_cs = ~ ip_cs;
return(ip_cs);
}
/** \brief Check IP frame's checksum
* \author
* \li Jari Lahti
* \date 11.06.2002
* \param frame pointer to IP frame to be checked
* \return
* \li 0 - checksum corrupted
* \li 1 - checksum OK
*
* Checksum of an IP packet is calculated and compared with the received
* checksum. Error is signaled if there is discrepancy between them.
*
*/
UINT8 ip_check_cs (struct ip_frame* frame)
{
UINT16 ip_cs;
UINT8 cs_cnt;
UINT8 olen;
UINT8 i;
ip_cs = 0;
cs_cnt = 0;
ip_cs = ip_checksum(ip_cs, frame->vihl, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->tos, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->tlen >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->tlen, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->id >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->id, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->frags >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->frags, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->ttl, cs_cnt++);
ip_cs = ip_checksum(ip_cs, frame->protocol, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->checksum >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->checksum, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 24), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 16), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->sip >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->sip, cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 24), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 16), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)(frame->dip >> 8), cs_cnt++);
ip_cs = ip_checksum(ip_cs, (UINT8)frame->dip, cs_cnt++);
/* Is there options? */
olen = ((frame->vihl & 0x0F) << 2) - IP_MIN_HLEN;
for( i=0; i<olen; i++)
ip_cs = ip_checksum(ip_cs, (UINT8)frame->opt[i], cs_cnt++);
/* Analyze the result */
ip_cs = ~ ip_cs;
if(ip_cs == IP_GOOD_CS)
return 1;
/* BEEEEEEP, it failed! */
return 0;
}
/** \brief Used for constructuing IP checksum
* \author
* \li Jari Lahti
* \date 24.02.2002
* \param cs last checksum value
* \param dat byte to be added to checksum
* \param count byte indicating whether dat is MSB or LSB byte
* \return new checksum value
*
* Based on count value, dat byte is added to checksum either as a MSB
* or a LSB byte and the new checksum value is then returned.
*
*/
UINT16 ip_checksum (UINT16 cs, UINT8 dat, UINT8 count)
{
UINT8 b = dat;
UINT8 cs_l;
UINT8 cs_h;
cs_h = (UINT8)(cs >> 8);
cs_l = (UINT8)cs;
if( count & 0x01 ) {
/* We are processing LSB */
if( (cs_l = cs_l + b) < b )
{
if( ++cs_h == 0 )
cs_l++;
}
} else
{
/* We are processing MSB */
if( (cs_h = cs_h + b) < b )
{
if( ++cs_l == 0 )
cs_h++;
}
}
return( ( (UINT16)cs_h << 8 ) + cs_l);
}
/** \brief Used for constructuing IP checksum of a data buffer
* \author
* \li Jari Lahti
* \date 03.08.2003
* \param cs last checksum value
* \param buf buffer who's checksum we're calculating
* \param len length of data in buffer
* \return new checksum value
*
* Calculates checksum of the data in buffer and returns new
* checksum value.
*/
UINT32 ip_checksum_buf (UINT16 cs, UINT8* buf, UINT16 len)
{
UINT16 dat;
UINT32 temp;
temp = cs;
while(len>1)
{
len -= 2;
dat = *buf++;
dat <<= 8;
dat |= *buf++;
temp += dat;
}
temp = (temp >> 16) + (temp & 0xFFFF); /* Add in carry */
temp += (temp >>16); /* Maybe one more */
if(len)
temp = (UINT32)(ip_checksum((UINT16)(temp), *buf, 0));
return((UINT16)temp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -