Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game. |
Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
12-09-2008, 09:01 AM
|
#1
|
LQ Newbie
Registered: Dec 2008
Posts: 11
Rep:
|
Please Help me : Sendto: Invalid argument PF_PACKET SOCK_DGRAM htons(ETH_P_IP)
Hi ,
Can somebody please help me find the problem with the code posted below.In that i am trying to get SOCK_DGRAM packets through ethernet device(both eth0 and lo) and calculating checksums and then printing IP and TCP headers along with checksum.I recieve packets using recvfrom function.I managed to get all the fields correct(i think so) including checksums.I am using a little endian machine. Then i try to send the same packet back to interface without any change.I use sendto for this purpose.But whatever i do sendto always returns "Invalid argument" error.I am after this problem for three days and could not advance past this error.I have browsed internet for a solution and tried all that i think might be causing the problem.but no success.Now i have no option other than posting it here and hoping that somebody will take a look at the code.
Here is the code....
(I have pasted a sample output also at the end.)
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define MY_MAXLEN 65535
#define BYTE unsigned char
#define WORD unsigned short
#define IP_VERSION 4
#define WINDOW_SIZE 256;
#define URG 0x20
#define ACK 0x10
#define PSH 0x8
#define RST 0x4
#define SYN 0x2
#define FIN 0x1
#define TRUE 1
#define FALSE 0
unsigned short in_cksum(unsigned short *addr,unsigned short len)
{
register int nleft = len;
register unsigned short *w = addr;
register int sum = 0;
unsigned short answer = 0;
while (nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if (nleft == 1)
{
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(ntohs(answer));
}
#pragma pack(1)
typedef struct
{
struct in_addr src_addr;
struct in_addr dst_addr;
BYTE res;
BYTE proto;
WORD tcp_len;
}PSEUDO_HDR;
/* i386 is little-endian. */
/*Linux localhost.localdomain 2.6.23.13 #2 PREEMPT Tue Jan 15 13:18:33 IST 2008 i686 i686 i386 GNU/Linux*/
int main()
{
int my_packet_sock;
BYTE my_buf[MY_MAXLEN];
int ret=0;
int i=0;
struct packet_mreq sockopt;
struct sockaddr_ll from;
socklen_t fromlen=0;
struct ip *iph=NULL;
struct tcphdr *tcph=NULL;
PSEUDO_HDR pseudo_hdr;
int len=0,padding=0;
BYTE *tmp_buf=NULL;
short tmp_sum=0;
if((my_packet_sock=socket(PF_PACKET,SOCK_DGRAM,htons(ETH_P_IP)))==-1)
{
perror("Socket Creation");
return FALSE;
}
printf("\nSocket Created Succefully\n");
sockopt.mr_ifindex=1; /* interface index */
sockopt.mr_type=PACKET_MR_PROMISC;/* action */
sockopt.mr_alen=0; /* address length */
sockopt.mr_address[0]='\0'; /* physical layer address */
if(setsockopt(my_packet_sock,SOL_PACKET,PACKET_ADD_MEMBERSHIP,(void
*)&sockopt,sizeof(sockopt))==-1)
{
perror("Set Socket Options");
return FALSE;
}
printf("\nSocket Options Set Succefully\n");
fromlen=sizeof(struct sockaddr_ll);
memset((BYTE *)&from,0x0,fromlen);
while((ret=recvfrom(my_packet_sock,(BYTE *)my_buf,MY_MAXLEN,0,(struct sockaddr *)&from,&fromlen))>0)
{
iph=(struct ip *)my_buf;
printf("\nIP Total Bytes Read=%d\nip header
length=%d:ip version=%d:ip type of service=%d:ip total length=
%d:ip identification=%d:ip fragment offset field=%d:ip time to
live=%d:ip protocol =%d:ip checksum=%x:ip source address=%s:
ip destaddress=%s\n",ret,iph->ip_hl,iph->ip_v,iph->ip_tos,
ntohs(iph->ip_len),iph->ip_id,iph->ip_off,iph->ip_ttl,
iph->ip_p,ntohs(iph->ip_sum),inet_ntoa(iph->ip_src),inet_ntoa(iph->ip_dst));
tmp_sum=iph->ip_sum;
iph->ip_sum=0;
printf("\n\nIP check sum is %x \n",in_cksum((unsigned short *)my_buf,iph->ip_hl)*4));
iph->ip_sum=tmp_sum;
printf("\nfromlen=%d,family=%x,protocol=%x,ifindex=%x,hatype=%x,
pkttype=%x,halen=%d "
,fromlen,from.sll_family,ntohs(from.sll_protocol),from.sll_ifindex,
from.sll_hatype,from.sll_pkttype,from.sll_halen);
for(i=0;i<8;i++)
{
printf(" %X",from.sll_addr[i]);
}
printf("\n");
i=0;
if(iph->ip_p==IPPROTO_TCP)
{
tcph=(struct tcphdr *)&my_buf[(iph->ip_hl)*4];
printf("\nTCP source port=%d,destination
port=%d,seq=%ld,ack=%ld,res1=%d,doff=%d,FIN=%d,SYN=%d,RST=%d,
PSH=%d,ACK=%d,URG=%d,res2=%d,window=%d,check=%x,urg_ptr=%d\n",
ntohs(tcph->source),ntohs(tcph->dest),ntohs(tcph->seq),
ntohs(tcph->ack_seq),tcph->res1,tcph->doff,tcph->fin,
tcph->syn,tcph->rst,tcph->psh,tcph->ack,tcph->urg,
tcph->res2,ntohs(tcph->window),ntohs(tcph->check),
ntohs(tcph->urg_ptr));
tmp_sum=tcph->check;
tcph->check=0;
pseudo_hdr.src_addr=iph->ip_src;
pseudo_hdr.dst_addr=iph->ip_dst;
pseudo_hdr.res=0;
pseudo_hdr.proto=iph->ip_p;
pseudo_hdr.tcp_len=htons(ntohs(iph->ip_len)-((iph->ip_hl)*4));
padding= (ntohs(iph->ip_len) - ((iph->ip_hl) * 4) - ((tcph->doff) *4))%2;
len=ntohs(pseudo_hdr.tcp_len)+sizeof(PSEUDO_HDR)+padding;
tmp_buf=calloc(len,1);
memcpy(tmp_buf,(PSEUDO_HDR *)&pseudo_hdr,sizeof(PSEUDO_HDR));
memcpy(tmp_buf+sizeof(PSEUDO_HDR),(BYTE
*)&my_buf[(iph->ip_hl)*4],ntohs(pseudo_hdr.tcp_len));
printf("\nTCP check sum is %x Pseudo size is %d Padding is
%d",in_cksum((unsigned short *)tmp_buf,len),sizeof(PSEUDO_HDR),padding);
free(tmp_buf);
tcph->check=tmp_sum;
if(tcph->ack)
{
if(sendto(my_packet_sock,my_buf,ntohs(iph->ip_len),0,(struct sockaddr
*)&from,fromlen)==-1)
{
perror("Sendto");
}
else
{
printf("\nSendto Success\n");
}
}
}
}
perror("Read Socket");
return FALSE;
}
Here is the output i get
[root@localhost rsocket]# ./dgram_sock.o
Socket Created Succefully
Socket Options Set Succefully
IP Total Bytes Read=52
ip header length=5:ip version=4:ip type of service=0:ip total length=52:ip identification=0:ip fragment offset field=64:ip time to live=48:ip protocol =6:ip checksum=d514:ip source address=202.58.12.98:ip dest address=202.58.12.98
IP check sum is d514
fromlen=18,family=11,protocol=800,ifindex=2,hatype=1,pkttype=0,halen=6 0 B 45 B6 70 40 0 0
TCP source port=80,destination port=41047,seq=59778,ack=62938,res1=0,doff=8,FIN=0,SYN=0,RST=0,PSH=0,ACK=1,URG=0,res2=0,window=64,ch eck=77c4,urg_ptr=0
Sendto: Invalid argument
TCP check sum is 77c4 Pseudo size is 12 Padding is 0
IP Total Bytes Read=52
ip header length=5:ip version=4:ip type of service=0:ip total length=52:ip identification=0:ip fragment offset field=64:ip time to live=48:ip protocol =6:ip checksum=d514:ip source address=202.58.12.98:ip dest address=202.58.12.98
IP check sum is d514
fromlen=18,family=11,protocol=800,ifindex=2,hatype=1,pkttype=0,halen=6 0 B 45 B6 70 40 0 0
TCP source port=80,destination port=41046,seq=59672,ack=63117,res1=0,doff=8,FIN=0,SYN=0,RST=0,PSH=0,ACK=1,URG=0,res2=0,window=71,ch eck=7916,urg_ptr=0
Sendto: Invalid argument
Thanks for reading,
somebody please help...........
Last edited by tuxtuxtux; 12-09-2008 at 09:00 PM.
Reason: formatting
|
|
|
12-09-2008, 09:57 PM
|
#2
|
LQ Newbie
Registered: Dec 2008
Posts: 11
Original Poster
Rep:
|
Thanks,i got the answer...
Hello everybody,
That issue is solved now.
Thanks to Rob from another forum.
I am posting it here for anybody
who is interested.
the solution in Rob's own words is..
"But, try this: just before the sendto() reset "fromlen" to the full "sizeof (struct sockaddr_ll)"...Why? If I'm reading my local kernel source correctly, sendto() on a packet socket will fail with EINVAL if you pass it any length less than that... And, yet, recvfrom() will give
you a short length which only corresponds to the sll_halen + rest of preceding fields (ie: only counting the length of the actual filled-in hardware address)... One of those two is likely wrong and should change in the kernel, IMHO... (I'd say that sendmsg() should be flexible enough to accept the shorter address...) But, failing changing the kernel, it looks like you have to bow to its wishes and pass it the full length... *shrug* "
...that was the issue and it is solved now.
"Bow your head,kneel and Worship.... the KERNEL"
thanks,
sree
|
|
|
02-24-2010, 06:45 AM
|
#3
|
LQ Newbie
Registered: Feb 2010
Posts: 1
Rep:
|
hi
can you tell what change you did in the piece of code,that worked properly now.
thanks
karthiga
|
|
|
03-24-2010, 07:08 AM
|
#4
|
LQ Newbie
Registered: Mar 2010
Posts: 1
Rep:
|
Wow, A decently formulated question and you actually took the effort to post back when you found the answer... Respect
|
|
|
All times are GMT -5. The time now is 11:02 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|