niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » *nix » BSD » FreeBSD
RAW SOCKET sendto fails
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
Author Message
peter_holmes2003@yahoo.co
*nix forums beginner


Joined: 02 Feb 2005
Posts: 2

PostPosted: Sun Feb 13, 2005 9:53 pm    Post subject: RAW SOCKET sendto fails Reply with quote

I am trying to send a packet over a RAW socket with the IP header
provided. The sendto() function returns "invalid argument". If I don't
suppy the IP header the program works fine. I am attaching my test
program below

Can someone suggest anything I am missing or doing wrong.





#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>

#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/if_ether.h> /* includes net/ethernet.h */

#define BUFFER_SIZE 1024


u_short
in_cksum(const u_short *addr, register int len, u_short csum)
{
register int nleft = len;
const u_short *w = addr;
register u_short answer;
register int sum = csum;

/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if (nleft == 1)
sum += htons(*(unsigned char *)w << Cool;

/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}


int
main(int argc, char * argv[])
{
int sock;
struct sockaddr_in sin;
unsigned short local_port;
unsigned char protocol;
char * buffer, * buffer2, * dnsdata;
struct ip * ip_header;
struct icmp * icmp_header;
char * remote_ip_str="10.10.10.10";
unsigned short buffer_size, buffer_size2;
int tmp, len;
short randomseq;

protocol = IPPROTO_ICMP;

local_port = atoi(argv[1]);

if ((sock = socket(AF_INET, SOCK_RAW, protocol)) < 0) {
perror("socket");
exit(1);
}
memset(& sin, 0, sizeof(sin));

tmp = 1;
setsockopt(sock, 0, IP_HDRINCL, & tmp, sizeof(tmp));

buffer_size = sizeof(struct ip) + sizeof(struct icmp);
buffer_size2 = BUFFER_SIZE;
buffer = (char *) malloc(buffer_size);
buffer2 = (char *) malloc(buffer_size2);

memset(buffer, 0, sizeof(buffer));

memset(& sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(remote_ip_str);

ip_header = (struct ip *) buffer;
ip_header->ip_hl = 5;
ip_header->ip_v = 4;
ip_header->ip_tos = 0;
ip_header->ip_len = htons(buffer_size);
ip_header->ip_id = rand();
ip_header->ip_ttl = 64;
ip_header->ip_off = 0x40;
ip_header->ip_p = protocol;
ip_header->ip_sum = 0; /* This will be done in the kernel */
ip_header->ip_dst.s_addr = inet_addr(remote_ip_str);
/* Leave src IP address blank, kernel will fill it out. */
//ip_header->ip_src = 0;

icmp_header = (struct icmp *) (ip_header + 1);
icmp_header->icmp_type = htons(ICMP_ECHO);
icmp_header->icmp_code = 0;
icmp_header->icmp_id = htons(local_port);
icmp_header->icmp_seq = 0;
icmp_header->icmp_cksum = in_cksum((const u_short *) icmp_header,
sizeof(struct icmp), 0);

dump((short *)ip_header, ntohs(ip_header->ip_len));

if (sendto(sock, buffer, buffer_size, 0, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in)) < 0)
{
perror("sendto");
}

printf("sent query\n");

len = sizeof(sin);
if (recvfrom(sock, buffer2, buffer_size2, 0, (struct sockaddr *)
&sin, &len) < 0) {
perror("recvfrom");
return 1;
}
printf("received response\n");

close(sock);
return 0;
}
Back to top
Giorgos Keramidas
*nix forums Guru


Joined: 10 May 2002
Posts: 330

PostPosted: Mon Feb 14, 2005 2:00 am    Post subject: Re: RAW SOCKET sendto fails Reply with quote

On 2005-02-13 14:53, peter_holmes2003@yahoo.com wrote:
Quote:
I am trying to send a packet over a RAW socket with the IP header
provided. The sendto() function returns "invalid argument". If I don't
suppy the IP header the program works fine. I am attaching my test
program below

#include <stdio.h
#include <errno.h
#include <time.h
#include <unistd.h
#include <stdlib.h
#include <string.h
#include <sys/types.h
#include <sys/time.h
#include <sys/socket.h

#include <netinet/in_systm.h
#include <netinet/in.h
#include <netinet/ip.h
#include <netinet/ip_icmp.h
#include <netinet/if_ether.h> /* includes net/ethernet.h */

#define BUFFER_SIZE 1024


u_short
in_cksum(const u_short *addr, register int len, u_short csum)
{
register int nleft = len;
const u_short *w = addr;
register u_short answer;
register int sum = csum;

/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

/* mop up an odd byte, if necessary */
if (nleft == 1)
sum += htons(*(unsigned char *)w << Cool;

/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}


int
main(int argc, char * argv[])
{
int sock;
struct sockaddr_in sin;
unsigned short local_port;
unsigned char protocol;
char * buffer, * buffer2, * dnsdata;
struct ip * ip_header;
struct icmp * icmp_header;
char * remote_ip_str="10.10.10.10";
unsigned short buffer_size, buffer_size2;
int tmp, len;
short randomseq;

protocol = IPPROTO_ICMP;

local_port = atoi(argv[1]);

if ((sock = socket(AF_INET, SOCK_RAW, protocol)) < 0) {
perror("socket");
exit(1);
}
memset(& sin, 0, sizeof(sin));

tmp = 1;
setsockopt(sock, 0, IP_HDRINCL, & tmp, sizeof(tmp));

buffer_size = sizeof(struct ip) + sizeof(struct icmp);
buffer_size2 = BUFFER_SIZE;
buffer = (char *) malloc(buffer_size);
buffer2 = (char *) malloc(buffer_size2);

memset(buffer, 0, sizeof(buffer));

memset(& sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr(remote_ip_str);

ip_header = (struct ip *) buffer;
ip_header->ip_hl = 5;
ip_header->ip_v = 4;
ip_header->ip_tos = 0;
ip_header->ip_len = htons(buffer_size);
ip_header->ip_id = rand();
ip_header->ip_ttl = 64;
ip_header->ip_off = 0x40;
ip_header->ip_p = protocol;
ip_header->ip_sum = 0; /* This will be done in the kernel */
ip_header->ip_dst.s_addr = inet_addr(remote_ip_str);
/* Leave src IP address blank, kernel will fill it out. */
//ip_header->ip_src = 0;

icmp_header = (struct icmp *) (ip_header + 1);
icmp_header->icmp_type = htons(ICMP_ECHO);
icmp_header->icmp_code = 0;
icmp_header->icmp_id = htons(local_port);
icmp_header->icmp_seq = 0;
icmp_header->icmp_cksum = in_cksum((const u_short *) icmp_header,
sizeof(struct icmp), 0);

dump((short *)ip_header, ntohs(ip_header->ip_len));

if (sendto(sock, buffer, buffer_size, 0, (struct sockaddr *) &sin,
sizeof(struct sockaddr_in)) < 0)
{
perror("sendto");
}

printf("sent query\n");

len = sizeof(sin);
if (recvfrom(sock, buffer2, buffer_size2, 0, (struct sockaddr *)
&sin, &len) < 0) {
perror("recvfrom");
return 1;
}
printf("received response\n");

close(sock);
return 0;
}

Can someone suggest anything I am missing or doing wrong.

Probably a lot of things:

- The order of the include headers is messed up.
- You have no prototype for in_cksum().
- You cast `const' off some pointers.
- You can dump() but there is no visible prototype for it.
- You blindly call atoi() on argv[1] without checking argc to make sure
there *is* an argument.
- You pass a literal zero instead of SOL_SOCKET to setsockopt().
- You don't check the return value of setsockopt(), but assume that it
always works. It may fail, but then you can't send custom, crafted IP
headers down the socket.
- The naming scheme of "buffer", "buffer2" and their associated lengths
is silly. Entirely non-intuitive and very error prone. I'd probably
go for hbuf (header buf) and dbuf (data buf) and hbuflen/dbuflen.
- The ip_len field of the IP header contains only the length of the IP
header plus the size of the ICMP header. It should really contain the
full length of the IP datagram.
- The ip_off field of the IP header contains the magic value 0x40, which
is very likely to be wrong if you don't really mean to send a packet
that is a fragment continuation without the start of the fragmented
packet itself.

Start by building the program with as much warnings as possible (i.e.
with WARNS=6), fixing the mistakes caught by that, and then check every
return of every call before sendto() for possible errors Smile
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 1 [2 Posts] View previous topic :: View next topic
The time now is Fri Jan 09, 2009 11:11 am | All times are GMT
navigation Forum index » *nix » BSD » FreeBSD
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts mail delivery to cyrus fails embedded Postfix 0 Mon Mar 03, 2008 2:43 pm
No new posts luxadm remove_device fails on a 280R Gary Mills Solaris 2 Thu Jul 20, 2006 6:29 pm
No new posts socket read modifies third parameter after the call: Very... jainarunk@gmail.com networking 1 Thu Jul 20, 2006 3:47 pm
No new posts Socket Sabotage Michael B Allen networking 0 Wed Jul 19, 2006 9:51 pm
No new posts What blocks a write to a socket pair? Joe networking 0 Wed Jul 19, 2006 3:08 pm

Debt Consolidation | Dirty Dozen Brass Band | Final Fantasy | Credit Cards | Debt Help
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.1772s ][ Queries: 16 (0.0873s) ][ GZIP on - Debug on ]