LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-16-2012, 12:19 PM   #1
DavidA
LQ Newbie
 
Registered: Aug 2011
Location: UK
Posts: 11

Rep: Reputation: Disabled
sendto() fails for raw socket


Hi

I want to use a Linux raw socket for sending and receiving packets.

I create my socket as follows:

int g_rawSocket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

Receiving packets from the socket works ok. But when I use sendto() I get an error:

struct sockaddr_in sin;
sin.sin_family = AF_PACKET;
sin.sin_port = htons(30000);
sin.sin_addr.s_addr = inet_addr("172.xx.xx.xxx"); // (I've obscured the ip address for the sake of this post)

int ret = sendto(g_rawSocket, pPacket, packetSizeBytes, 0, (struct sockaddr *)&sin, sizeof(sin) );
if (ret < 0)
{
perror();
}

The error I get is:

"Invalid argument"

Is there anything wrong with my code?

Could the fault be in the packet itself?

I would be grateful for any help.

BR

David
 
Old 10-16-2012, 03:45 PM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,535

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
It would be helpful to see all your code, just see if you missed in critical error-checking tests while setting up the socket and your data.

Also, it would be helpful to know how you ran the application.
 
Old 10-16-2012, 04:02 PM   #3
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
I'm pretty sure that will not work. SOCK_RAW is a way to work outside of the IP stack. You will have to compose your IP datagram in it's entirety, and send it that way. If it elicits a reply, your raw socket will probably never see it, since the IP stack will grab it first. You can use write() to send your datagram(s) on the open raw socket.

--- rod.
 
Old 10-16-2012, 05:17 PM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,535

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by theNbomr View Post
I'm pretty sure that will not work. SOCK_RAW is a way to work outside of the IP stack. You will have to compose your IP datagram in it's entirety, and send it that way. If it elicits a reply, your raw socket will probably never see it, since the IP stack will grab it first. You can use write() to send your datagram(s) on the open raw socket.

--- rod.
That's not true. It's possible to build the raw IP datagram using a pre-allocated buffer in which one can map the IP header, the TCP header, and even the data. Sending this buffer using sendto() is also allowed. As I posted earlier, I need to see more code before I can pass judgement on what the OP is attempting.

There's rarely any sane reason for a beginner to want to use raw sockets in this manner. But I guess the OP is on a quest to see if he can issue packets that spoof the source IP address.

EDIT:

I just noticed that the OP is using PF_PACKET; perhaps you are correct in that SOCK_RAW cannot be used in that fashion. I know that SOCK_RAW can be used with PF_INET.

Last edited by dwhitney67; 10-16-2012 at 05:54 PM.
 
Old 10-16-2012, 06:58 PM   #5
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,398
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Okay, now I'm confused. What do you mean by 'raw IP datagram'? To me, raw means unadorned with TCP/IP header. Are you saying you can use the IP stack to compose the TCP/IP headers, but then wrap it with the ethernet addresses and so on to send it? I can't think of a reason why one would want to do such a thing. I can't think of why the OP would want to do what he is asking, but maybe they're the same thing.
--- rod.
 
Old 10-16-2012, 09:25 PM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,535

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by theNbomr View Post
Okay, now I'm confused. What do you mean by 'raw IP datagram'? To me, raw means unadorned with TCP/IP header. Are you saying you can use the IP stack to compose the TCP/IP headers, but then wrap it with the ethernet addresses and so on to send it? I can't think of a reason why one would want to do such a thing. I can't think of why the OP would want to do what he is asking, but maybe they're the same thing.
--- rod.
Sometimes I wonder myself what is the breadth of my knowledge with respect to socket programming; it's probably not that great. But I do have a sample program I wrote (in C++, using a library I threw together) that does indeed compose the TCP/IP headers. Here's a partial view of that code:
Code:
...

RawData BuildTcpDatagram(socketpp::TCPClientSocket& sock,
                         const std::string& servAddr, unsigned short servPort,
                         unsigned int seqnum, const RawData& msg)
{
  // Obtain the destination and source addresses to be inserted into the IP header
  sockaddr_in dst_sin;
  sockaddr_in src_sin;

  sock.fillAddress(reinterpret_cast<sockaddr*>(&dst_sin), sizeof(dst_sin), servPort, servAddr.c_str());
  sock.fillAddress(reinterpret_cast<sockaddr*>(&src_sin), sizeof(src_sin), 12345, "127.0.0.1");

  // this buffer will contain IP header, TCP header, and payload. we'll point an ip
  // header structure at its beginning, and a TCP header structure after that to write
  // the header values into it.
  unsigned char* datagram = new unsigned char[sizeof(ip) + sizeof(tcphdr) + msg.size()];

  // setup offsets to mark our header and data regions
  ip* iph    = reinterpret_cast<ip*>(datagram);
  int ip_len = sizeof(ip) + sizeof(tcphdr) + msg.size();

  iph->ip_hl         = sizeof(ip) >> 2;       // 5 words (20 bytes), but could be more!
  iph->ip_v          = 4;                     // IPv4
  iph->ip_tos        = 0;
  iph->ip_len        = htons(ip_len);         // the total length of the datagram
  iph->ip_id         = htons(54321);          // the value doesn't matter here
  iph->ip_off        = 0;
  iph->ip_ttl        = 255;
  iph->ip_p          = IPPROTO_TCP;
  iph->ip_sum        = 0;                      // set to 0; compute checksum later
  iph->ip_src.s_addr = src_sin.sin_addr.s_addr;
  iph->ip_dst.s_addr = dst_sin.sin_addr.s_addr;
  //iph->ip_src.s_addr = inet_addr(servAddr.c_str());
  //iph->ip_dst.s_addr = inet_addr("127.0.0.1");

  // compute checksum for the IP header (this is optional)
  iph->ip_sum = socketpp::headerChecksum(reinterpret_cast<uint16_t*>(iph), iph->ip_hl << 2);

  // now obtain our other data pointers
  tcphdr*        tcph = reinterpret_cast<tcphdr*>(datagram + (iph->ip_hl << 2));
  unsigned char* data = datagram + (iph->ip_hl << 2) + sizeof(tcphdr);

  // assign the message data
  memcpy(data, msg.data(), msg.size());

  // we'll now fill in the TCP header values
  tcph->source  = htons(0);
  tcph->dest    = htons(servPort);
  tcph->seq     = htonl(seqnum);
  tcph->ack_seq = htonl(0);
  tcph->res1    = 0;
  tcph->doff    = sizeof(tcphdr) >> 2;
  tcph->fin     = 0;
  tcph->syn     = 0;
  tcph->rst     = 0;
  tcph->psh     = 0;
  tcph->ack     = 0;
  tcph->urg     = 0;
  tcph->res2    = 0;
  tcph->window  = htons(TCP_MAXWIN);
  tcph->check   = 0;
  tcph->urg_ptr = htons(0);

  // now compute the TCP checksum
  uint16_t*    buffer     = 0;
  unsigned int bufferSize = socketpp::buildPseudoHdrBuffer(src_sin.sin_addr.s_addr, dst_sin.sin_addr.s_addr,
                                                           IPPROTO_TCP,
                                                           reinterpret_cast<uint8_t*>(tcph), sizeof(tcphdr),
                                                           msg.data(), msg.size(),
                                                           &buffer);

  tcph->check = socketpp::headerChecksum(buffer, bufferSize);

  RawData rd(datagram, datagram + ip_len);

  delete [] datagram;
  delete [] buffer;

  return rd;
}
The socket was created using the PF_INET domain, the SOCK_RAW type, and the IPPROTO_TCP protocol.

P.S. If you are wondering about RawData, it is defined as follows:
Code:
typedef std::basic_string<unsigned char> RawData;

Last edited by dwhitney67; 10-16-2012 at 09:26 PM.
 
Old 10-17-2012, 07:53 AM   #7
DavidA
LQ Newbie
 
Registered: Aug 2011
Location: UK
Posts: 11

Original Poster
Rep: Reputation: Disabled
Thanks for your replies and help.

I have fixed the error by passing a different structure type in parameter 5:

code was:

Code:
struct sockaddr_in sin;
... 
int ret = sendto(g_rawSocket, pPacket, packetSizeBytes, 0, (struct sockaddr *)&sin, sizeof(sin) );
code is now:

Code:
struct sockaddr_ll device;
...
int ret = sendto(g_rawSocket, auipPacket, auiSizeBytes, 0, (struct sockaddr *)&device, sizeof(device) );
Still some way to go, but it's looking better.
 
  


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
syslogd: sendto: Socket operation on non-socket PoleStar Other *NIX 1 06-07-2011 12:49 PM
Raw socket - max frame length supported by sendto call for tag frames muruga86 Linux - Networking 0 06-17-2010 07:45 AM
Multithread udp socket client fails to sendto data dilin Programming 0 04-06-2007 10:07 AM
sendto error (socket) payal_shah Linux - Networking 0 02-23-2005 01:18 PM
nmap raw packet sendto error in Mandrake 9.2 conn-fused Linux - Networking 0 06-30-2004 03:11 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:26 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration