|
|
|
|
|
|
| Author |
Message |
peter_holmes2003@yahoo.co *nix forums beginner
Joined: 02 Feb 2005
Posts: 2
|
Posted: Sun Feb 13, 2005 9:53 pm Post subject:
RAW SOCKET sendto fails
|
|
|
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 << ;
/*
* 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
|
Posted: Mon Feb 14, 2005 2:00 am Post subject:
Re: RAW SOCKET sendto fails
|
|
|
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 << ;
/*
* 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  |
|
| Back to top |
|
 |
Google
|
|
| Back to top |
|
 |
|
|
The time now is Fri Jan 09, 2009 11:11 am | All times are GMT
|
|
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
|
|