LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Networking
User Name
Password
Linux - Networking This forum is for any issue related to networks or networking.
Routing, network cards, OSI, etc. Anything is fair game.

Notices


Reply
  Search this Thread
Old 12-09-2008, 09:01 AM   #1
tuxtuxtux
LQ Newbie
 
Registered: Dec 2008
Posts: 11

Rep: Reputation: Disabled
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
 
Old 12-09-2008, 09:57 PM   #2
tuxtuxtux
LQ Newbie
 
Registered: Dec 2008
Posts: 11

Original Poster
Rep: Reputation: Disabled
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
 
Old 02-24-2010, 06:45 AM   #3
skarthiga24
LQ Newbie
 
Registered: Feb 2010
Posts: 1

Rep: Reputation: 0
hi

can you tell what change you did in the piece of code,that worked properly now.

thanks
karthiga
 
Old 03-24-2010, 07:08 AM   #4
daniel.reus
LQ Newbie
 
Registered: Mar 2010
Posts: 1

Rep: Reputation: 0
Thumbs up

Wow, A decently formulated question and you actually took the effort to post back when you found the answer... Respect
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
IPTABLES - Invalid argument initialdrifteg6 Linux - Networking 1 03-06-2008 07:23 PM
message sending failed : Error[22 ] invalid argument .....but each and every argument rakeshranjanjha Linux - Software 2 01-08-2008 12:22 AM
br2684ctl Invalid argument kenjiru Linux - Hardware 1 04-14-2007 04:51 AM
sendto: invalid argument Yury Programming 12 11-04-2006 07:06 AM
Invalid Argument Error ahmedb72 Red Hat 1 02-25-2006 08:52 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Networking

All times are GMT -5. The time now is 11:02 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration