PDA

View Full Version : Ask for a strange question



leetow2003
07-15-2011, 12:55 AM
I write codes about sending TCP packet and receiving IP and TCP packet,
I create a socket:
sk=socket(AF_INET,SOCK_RAW,IPPROTO_TCP);
if I set the option:
setsockopt(sk, IPPROTO_IP, IP_HDRINCL,&on,sizeof(on));(int on=1)
then I send combining packet of IP and TCP ,then I can receive IP and TCP packet.
If I don't set the option IP_HDRINCL,and I send only TCP packet,
when I receive packet,it display error:Resource temporarily unavailable.
Who could tell me why?and how to correct it?thank you very much.

leetow2003
07-15-2011, 02:46 AM
And I find If I set my local IP to real IP(not INADDRY_ANY),when I recieve it
display "invalid argument" ,if I set my local IP to INADDRY_ANY,when I recieve it
display "Resource temporarily unavailable" .My codes send TCP packet at first,
and then receive data.Who could tell me why?and how to correct it?

anduril462
07-15-2011, 10:34 AM
I write codes about sending TCP packet and receiving IP and TCP packet,
Code? What code? I don't see any code. It's near impossible for us to troubleshoot this without code.


Who could tell me why?and how to correct it?thank you very much.
Nobody. Not because your question is impossible to answer, because we don't have enough information.

What are you communicating with or using to generate the packets for testing? Are you sure that doesn't have a bug?

Read the following man pages: socket(7), ip(7), packet(7), raw(7)
The 7 is for section 7, so do "man 7 socket".

Here's a StackOverflow article (http://stackoverflow.com/questions/110341/tcp-handshake-with-sock-raw-socket) that looks related. Maybe some of the info there will give you some clues.

leetow2003
07-16-2011, 07:03 PM
Because my codes are too long,
Look:


#define LOCALPORT 8888
//pseudo header,12 bytes
struct prseuheader
{
unsigned long s_addr;//resource addr
unsigned long d_addr;//dest addr
unsigned char zero; //0
unsigned char prototp;//tcp=6
unsigned short len; //length
};

/*20 bytes*/
struct IP_Head
{
unsigned char length:4;
unsigned char version:4;
unsigned char tos;
unsigned short total_length;
unsigned short id;
unsigned short flagoff;
unsigned char ttl;
unsigned char protocol;
unsigned short cksum;
unsigned int source;
unsigned int dest;
};

/* 20 bytes */
struct TCP_Head
{
unsigned short source_port;
unsigned short dest_port;
unsigned int seqno;
unsigned int ackno;
unsigned char rev1:4;
unsigned char len:4;
unsigned char fin:1;
unsigned char syn:1;
unsigned char rst:1;
unsigned char psh:1;
unsigned char ack:1;
unsigned char urg:1;
unsigned char rev2:2;
unsigned short winsize;
unsigned short cksum;
unsigned short urgent;
};

static struct sockaddr_in Localaddr;//Local IP address
static struct sockaddr_in RemoteAddr;//remote IP address

/* Checksum */
unsigned short checksum(unsigned short* buffer, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buffer++;
size -= 2;
}
if(size)
{
cksum += *(u_char*)buffer;
}
cksum = (cksum>>16) + (cksum&0xffff);
cksum += (cksum>>16);
return (unsigned short)(~cksum);
}

//main
int main()
{
int sk;
char ipaddr[16]="192.168.1.6";//remote IP
struct in_addr in;
inet_aton(ipaddr,&in);
//set RemoteAddr
bzero(&RemoteAddr,sizeof(struct sockaddr_in));
RemoteAddr.sin_family=AF_INET;
RemoteAddr.sin_addr=in;

sk=socket(AF_INET,SOCK_RAW,IPPROTO_TCP); //create SOCK_RAW
if(sk<0)
{
perror("socket error");
return -1;
}

int iRet;
struct timeval timeout={1,0}; //timeout
int len=sizeof(struct timeval);

//set timeout
iRet =setsockopt(sk,SOL_SOCKET,SO_SNDTIMEO, &timeout,len);
if (iRet<0)
{
perror("[Error]Set socket SO_SNDTIMEO option");
close(sk);
return -1;
}
iRet =setsockopt(sk,SOL_SOCKET,SO_RCVTIMEO, &timeout,len);
if (iRet<0)
{
perror("[Error]Set socket SO_RCVTIMEO option");
close(sk);
return -1;
}


bzero(&Localaddr,sizeof(struct sockaddr_in));
Localaddr.sin_family=AF_INET;
Localaddr.sin_addr.s_addr=inet_addr("192.168.124.128"); //My PC's real IP

iRet = bind(sk,(struct sockaddr*)&Localaddr,sizeof(struct sockaddr));
if (iRet<0)
{
perror("[Error]Bind sk the interface");
close(sk);
return -1;
}

struct TCP_Head Tcph;//TCP packet
struct IP_TCP_Head
{
struct IP_Head Iph;
struct TCP_Head Tcph;
}*Reply; //for receiving
struct prseuheader theheader;//pseudo header
char tcpbuff[32]; //pseudo header and TCP header
unsigned char buffer[200]; //buffer for receiving
struct sockaddr_in taddr; //
int lenfrom,lenrecv;

bzero(&Tcph,20);
Tcph.source_port =htons(8888);//local port
//Tcph.dest_port =htons(21);//dest port;
Tcph.seqno =0;
Tcph.ackno =0;
Tcph.len =5;
Tcph.syn =1; //SYN=1
Tcph.winsize =htons(6000);
Tcph.cksum =0;
bzero(tcpbuff,32);
//fill
theheader.s_addr = Localaddr.sin_addr.s_addr;
theheader.d_addr = RemoteAddr.sin_addr.s_addr;
theheader.zero = 0;
theheader.prototp = 6; // protocol of TCP
theheader.len = htons(20); //length of TCP
//pseudo header+TCP header
memcpy(tcpbuff,&theheader,12);
memcpy(tcpbuff+12,&Tcph,20);
//Tcph.cksum =checksum((unsigned short *)tcpbuff,32);
int port=21;
//for(port=1;port<30;port++)
{
Tcph.dest_port =htons(port);
memcpy(tcpbuff+12,&Tcph,20);
Tcph.cksum =0;
Tcph.cksum =checksum((unsigned short *)tcpbuff,32);
//sending data
iRet=sendto(sk,(unsigned char*)&Tcph,20,0,(struct sockaddr*)&RemoteAddr,sizeof(struct sockaddr_in));
if(iRet<0)
perror("error sendto");
//receiving data
bzero(buffer,200);
bzero(&taddr,sizeof(taddr));
lenrecv=recvfrom(sk,buffer,200,0,(struct sockaddr*)&taddr,&lenfrom);
if(lenrecv>0) /*it express PC has received data*/
{
Reply=(struct IP_TCP_Head*)buffer;
printf("syn,ask=%d,%d\n",(Reply->Tcph).syn,(Reply->Tcph).ack);
if((Reply->Tcph).syn==1 &&(Reply->Tcph).ack==1 && (Reply->Iph).source==RemoteAddr.sin_addr.s_addr && (Reply->Iph).dest==Localaddr.sin_addr.s_addr)
{
printf("active Port:%d\n",21);
bzero(Reply,sizeof(Reply));
}

}
else
{
//it always displays
printf("len=%d\n",lenrecv);
perror("recv len");

}
}
return 0;
}

anduril462
07-18-2011, 12:03 PM
That code is not too long, and very necessary for our helping you. It would be nice if you showed which headers you included as well. Did you read the man pages thoroughly for all the functions you're using? I'm guessing not. A quick Google search would tell you that "Resource temporarily unavailable" was tied to EAGAIN or EWOULDBLOCK. So looking at the man page:


ERRORS
These are some standard errors generated by the socket layer. Additional errors may be generated and returned from the underlying protocol modules; see their manual
pages.


EAGAIN or EWOULDBLOCK
The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.
POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check
for both possibilities.


That's probably why you're getting that error message. You set a timeout of 1 second, and it expired. Again, I can't say for sure what the origin of that error is, but for some reason 192.168.1.6 is not replying. Perhaps you have some malformed packets. Perhaps nothing is actually listening on that IP/port on the TCP protocol. Port 21 is FTP, so are you sure you can connect from 192.168.124.128 to .1.6 on port 21? Use the standard Linux FTP client. Capture that dialogue with Wireshark. Then, run your program and capture that dialogue with Wireshark. Compare the two. How is your SYN packet different that of the working FTP client's? Also, is there a reason you have the checksum commented out?


Lastly, you should stop using bzero as it's deprecated. Just use memset (again, the man page tells you this).

leetow2003
07-18-2011, 08:34 PM
I can connect 192.168.1.6 port 21 using command ftp,and just now I find if
set recvfrom buffer to 2000,it runs well,why?

anduril462
07-18-2011, 11:15 PM
The only way I can imagine enlarging your receive buffer could affect how the program works is if you have a buffer overflow somewhere. If that buffer overflow used to destroy other variables on the stack, and now it can't get that far up the stack because buffer is too big, then that might explain it. I didn't see anything, but that doesn't mean I didn't miss it. I found your code a little messy and hard to follow. Try using valgrind (http://valgrind.org/) and electric fence (http://elinux.org/Electric_Fence) to make sure you're behaving yourself, and maybe step through your code in GDB and inspect every value as you go.

If that's not the issue, then perhaps something on the network or remote server changed since this morning. Otherwise, I have no ideas at the moment.