A
Andreas Mueller
I'm having a problem using select with a Raw-Socket.
I get a packet, change the IP address (for sending it to a tun device)
and then I try to recalculate the IP-checksum.
If I do so, it loops forever with the same packet. If I don't use
either(!) ip->check = 0; or ip->check = in_cksum... the code works fine.
Does anybody see what the problem is?
thanks in advance,
Andreas
for( ;; ) {
FD_ZERO( &read_fds );
FD_SET( sUDP, &read_fds );
ret_val = select( sUDP + 1, &read_fds, NULL, NULL, NULL );
if( ret_val < 0 )
break;
if( ret_val > 0 ) {
if ( FD_ISSET( sUDP, &read_fds ) ) {
int lenInUDP = recvfrom(sUDP, ðBufferUDP,
sizeof(ethBufferUDP), 0, 0, 0);
ip = (struct iphdr *) ethBufferUDP;
//change source address to interface address
ip->saddr = inet_addr("172.16.1.20");
//change destination address to 134.2.173.55
ip->daddr = inet_addr("172.16.1.1");
/***************PROBLEM HERE*******************************************/
ip->check = 0;
ip->check = in_cksum ((unsigned short *) ip, ip->ihl * (32 / 8));
}
}
}
here's the code for in_chksum:
unsigned short in_cksum (unsigned short *addr, int count) {
register long sum = 0;
register unsigned short checksum;
while (count > 1)
{
sum += *addr++;
count -= 2;
}
if (count > 0)
{
sum += *(unsigned char *) addr;
}
while (sum >> 16)
{
sum = (sum & 0xffff) + (sum >> 16);
}
checksum = ~sum;
return checksum;
}
I get a packet, change the IP address (for sending it to a tun device)
and then I try to recalculate the IP-checksum.
If I do so, it loops forever with the same packet. If I don't use
either(!) ip->check = 0; or ip->check = in_cksum... the code works fine.
Does anybody see what the problem is?
thanks in advance,
Andreas
for( ;; ) {
FD_ZERO( &read_fds );
FD_SET( sUDP, &read_fds );
ret_val = select( sUDP + 1, &read_fds, NULL, NULL, NULL );
if( ret_val < 0 )
break;
if( ret_val > 0 ) {
if ( FD_ISSET( sUDP, &read_fds ) ) {
int lenInUDP = recvfrom(sUDP, ðBufferUDP,
sizeof(ethBufferUDP), 0, 0, 0);
ip = (struct iphdr *) ethBufferUDP;
//change source address to interface address
ip->saddr = inet_addr("172.16.1.20");
//change destination address to 134.2.173.55
ip->daddr = inet_addr("172.16.1.1");
/***************PROBLEM HERE*******************************************/
ip->check = 0;
ip->check = in_cksum ((unsigned short *) ip, ip->ihl * (32 / 8));
}
}
}
here's the code for in_chksum:
unsigned short in_cksum (unsigned short *addr, int count) {
register long sum = 0;
register unsigned short checksum;
while (count > 1)
{
sum += *addr++;
count -= 2;
}
if (count > 0)
{
sum += *(unsigned char *) addr;
}
while (sum >> 16)
{
sum = (sum & 0xffff) + (sum >> 16);
}
checksum = ~sum;
return checksum;
}