Not receiving SYN/ACK after sending SYN using RAW socket - c

I am sending TCP SYN packets (with no payload) to a webserver in the same network. I am using sniffex.c
for capturing the packets .
The problem is that after I send a SYN packet, I do not receive the SYN/ACK packet from server.
In sniffex.c:
I have used my LAN IP as the source ip.
I have set the filter as "tcp" .
I am sending to port 80
When i print the fields of the sent packet ,after i capture it using sniffex , all fields are printed correctly, hence i assume that the structure of the sent packet is such that the server can understand it.
When I connect to the webserver using browser, the SYN/ACK is received successfully.
Another related query: how do I set the filter such that I get packets relating to this conversation (b/w my pc and webserver) only
I am using UBUNTU 14.04
EDIT: The c file with which I am trying to send the packet
#define __USE_BSD /* use bsd'ish ip header */
#include <sys/socket.h> /* these headers are for a Linux system, but */
#include <netinet/in.h> /* the names on other systems are easy to guess.. */
#include <netinet/ip.h>
#define __FAVOR_BSD /* use bsd'ish tcp header */
#include <netinet/tcp.h>
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<errno.h>
#include<sys/socket.h>
#include<sys/types.h>
#define P 80 /* lets flood the sendmail port */
unsigned short /* this function generates header checksums */
csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int
main (void)
{
int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);
printf("s=%d\n",s); /* open raw socket */
char datagram[4096]; /* 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 */
struct ip *iph = (struct ip *) datagram;
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
struct sockaddr_in sin;
/* the sockaddr_in containing the dest. address is used
in sendto() to determine the datagrams path */
sin.sin_family = AF_INET;
sin.sin_port = htons (P);/* you byte-order >1byte header values to network
byte order (not needed on big endian machines) */
sin.sin_addr.s_addr = inet_addr ("xxx.xxx.xxx.xxx");
memset (datagram, 0, 4096); /* zero out the buffer */
/* we'll now fill in the ip/tcp header values, see above for explanations */
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr); /* no payload */
iph->ip_id = htonl (54321); /* the value doesn't matter here */
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0; /* set it to 0 before computing the actual checksum later */
iph->ip_src.s_addr = inet_addr ("xxx.xxx.xxx.xxx");/* SYN's can be blindly spoofed */
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->th_sport = htons (2000); /* arbitrary port */
tcph->th_dport = htons (P);
tcph->th_seq = random();/* in a SYN packet, the sequence is a random */
tcph->th_ack = 0;/* number, and the ack sequence is 0 in the 1st packet */
tcph->th_x2 = 5;
tcph->th_off = 5; /* first and only tcp segment */
tcph->th_flags = TH_SYN; /* initial connection request */
tcph->th_win = htonl (65535); /* maximum allowed window size */
tcph->th_sum = 0;/* if you set a checksum to zero, your kernel's IP stack
should fill in the correct checksum during transmission */
tcph->th_urp = 0;
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
/* finally, it is very advisable to do a IP_HDRINCL call, to make sure
that the kernel knows the header is included in the data, and doesn't
insert its own header into the packet before our data */
/* lets do it the ugly way.. */
int one = 1;
// const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, &one, sizeof (one)) < 0)
printf ("Warning: Cannot set HDRINCL!\terrno = %d\n",errno);
// while (1)
// {
if (sendto (s, /* our socket */
datagram, /* the buffer containing headers and data */
iph->ip_len, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof (sin)) < 0) /* a normal send() */
printf ("error\n");
else
printf ("SUCCESS\n\n\n\n");
//}
char buffer[8192];
memset (buffer, 0, 8192);
int n;
//while(n=read (s, buffer, 8192) > 0)
//{
//printf("n=%d\n",n);
//printf ("Caught tcp packet: %s\n", buffer);
//memset (buffer, 0, 8192);
//}
return 0;
}

[Summary of chat session]
In addition to the iph->ip_off issue, you may need to compute the TCP checksum yourself (your O/S may not do it for you). Useful info is here: http://www.tcpipguide.com/free/t_TCPChecksumCalculationandtheTCPPseudoHeader-2.htm and http://www.netfor2.com/tcpsum.htm
Also tcph->th_seq = htonl(23456); may be useful.

Related

C Networking: Sendto() returning Errno 22, EINVAL

I'm attempting to generate a packet from scratch with Layer 2, 3, and 4 components (namely Ethernet, IP, and UDP). My socket is configured to use SOCK_RAW as the type and IPPROTO_RAW as the protocol, so that my program can be used to send different protocols at a later date. I've strictly abided by the sendto(2) man page (https://linux.die.net/man/2/sendto), however, I still seem to be having troubles transmitting a packet over local host. The error returned by my program is 22, or EINVAL, indicating that I've passed an incorrect argument.
I've already used Sockets sendto() returning EINVAL and Socket programming: sendto always fails with errno 22 (EINVAL) in attempt to resolve my problem. I've even switched the socket to use SOCK_DGRAM as the type and IPPROTO_UDP as the protocol to see if it was something to do with the socket (though I don't believe this would have prompted an incorrect argument response).
My code is as follows:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/ip.h>
#include <netinet/ether.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <errno.h>
#define BUFFER 1024
int main(int argc, char *argv[]) {
/* Socket Creation */
int sockfd;
if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
perror("Socket");
exit(EXIT_FAILURE);
}
// This will hold all of the packet's contents
char sendbuf[BUFFER];
/* Address Stuff */
// Specify Address
in_addr_t address = inet_addr("127.0.0.1");
// Specifying Address for Sendto()
struct sockaddr_in sendto_addr;
memset(&sendto_addr, 0, sizeof(sendto_addr));
sendto_addr.sin_family = AF_INET;
sendto_addr.sin_port = htons(9623); // Make sure the port isn't contested
sendto_addr.sin_addr.s_addr = address;
// Size of whole packet
size_t total_len = 0;
/* LAYER 2 */
// Ethernet Header Configuration
struct ether_header *ether = (struct ether_header *)sendbuf;
int i;
for (i = 0; i < 6; ++i) {
ether -> ether_dhost[i] = 0x00; // Temporary data fill
ether -> ether_shost[i] = 0x00; // Temporary data fill
}
ether -> ether_type = ETHERTYPE_IP;
total_len += sizeof(struct ether_header);
/* LAYER 3 */
// IP Header Configuration
struct ip *ip = (struct ip *)(sendbuf + sizeof(struct ether_header));
ip -> ip_hl = 5;
ip -> ip_v = 4;
ip -> ip_tos = 0;
ip -> ip_p = 17;
ip -> ip_ttl = 255;
ip -> ip_src.s_addr = address;
ip -> ip_dst.s_addr = address;
total_len += sizeof(struct ip);
/* LAYER 4 */
// UDP Header Configuration
struct udphdr *udp = (struct udphdr *)(sendbuf + sizeof(struct ether_header) + \
sizeof(struct ip));
udp -> source = 123; // Gibberish to fill in later
udp -> dest = 321; // Gibberish to fill in later
udp -> check = 0;
total_len += sizeof(struct udphdr);
/* Giberrish Packet Data */
sendbuf[total_len++] = 0x00;
sendbuf[total_len++] = 0x00;
sendbuf[total_len++] = 0x00;
sendbuf[total_len++] = 0x00;
/* Fill in Rest of Headers */
udp -> len = htons(total_len - sizeof(struct ether_header) - sizeof(struct ip));
ip -> ip_len = htons(total_len - sizeof(struct ether_header));
/* Send Packet */ // ERROR OCCURS HERE
printf("Sockfd is %d\n", sockfd);
printf("Total length is %d\n", total_len);
if (sendto(sockfd, sendbuf, total_len, 0, (const struct sockaddr*)&sendto_addr, \
sizeof(sendto_addr)) < 0) {
printf("Error sending packet: Error %d.\n", errno);
perror("sendto Error");
exit(EXIT_FAILURE);
}
close(sockfd);
}
The precise console message states:
Sockfd is 3
Total length is 46
Error sending packet: Error 22.
sendto Error: Invalid argument
Eureka! It was actually this line:
if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {
perror("Socket");
exit(EXIT_FAILURE);
}
Which should have been
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("Socket");
exit(EXIT_FAILURE);
}
Why this fixed the problem? Great question, would love to see someone's response on the subject :P

No output when using raw socket to send spoofed packets via multicast to different subnet

My application is a specialized user space UDP router that uses raw sockets to produce unicast and multicast output with actual or spoofed source addresses in the IP packet headers of the sent packets.
Briefly, there is one permutation of the outputs that fails to reach some of the destination hosts.
My question: is there some subtle logic in the Linux stack that prevents certain routing permutations, or is the output function I am using missing something?
I can't create a UDP packet writer that successfully sends packets that (1) contain a spoofed source address, (2) to a multicast address, (3) if sending host is on subnet A, (4) receiving host is on subnet B, if the (valid) spoofed source address is on subnet A.
Subnet A = 10.200.xx.nn
Subnet B = 10.200.yy.nn
Source address in packet = sending host
Subnet
Src addr = sender addr A A B B
Receiver A B A B
Result Yes Yes Yes Yes
Source address in packet != sending host
Subnet
Sender A A A A B B B B
Spoofed src addr A A B B A A B B
Receiver A B A B A B A B
Result Yes Yes Yes No No Yes Yes Yes
The spoof addresses are to existing network devices.
Wireshark run on the failing destinations shows no UDP data.
My raw socket class is derived very closely from the example program I found at Stack Overflow kindly donated by user Peter O. on March 11, 2012 - question 3737612 "Raw socket sendto failed using C on Linux". I have appended my version of it, with a
couple of enhancements/fixes. I compiled and ran it on RedHat 5, gcc 4.1.2.
I checked /etc/sysctl.conf entries that might be relevant, and set the following with no discernable effect:
sudo /sbin/sysctl -w net.ipv4.conf.default.rp_filter=0
sudo /sbin/sysctl -w net.ipv4.conf.eth2.rp_filter=0
sudo /sbin/sysctl -w net.ipv4.conf.lo.rp_filter=0
sudo /sbin/sysctl -w net.ipv4.conf.all.rp_filter=0
sudo /sbin/sysctl -w net.ipv4.ip_forward=1
sudo /sbin/sysctl -w net.ipv4.conf.default.accept_source_route=1
sudo /sbin/sysctl -w net.ipv4.conf.all.accept_source_route=1
My modified version of the example from 3737612 is appended.
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <time.h>
//The packet length in byes
#define PCKT_LEN 50
//Date size in bytes
#define DATA_SIZE 15
//PseudoHeader struct used to calculate UDP checksum.
typedef struct PseudoHeader{
unsigned long int source_ip;
unsigned long int dest_ip;
unsigned char reserved;
unsigned char protocol;
unsigned short int udp_length;
}PseudoHeader;
// Ripped from Richard Stevans Book
unsigned short ComputeChecksum(unsigned char *data, int len)
{
long sum = 0; /* assume 32 bit long, 16 bit short */
unsigned short *temp = (unsigned short *)data;
while(len > 1){
sum += *temp++;
if(sum & 0x80000000) /* if high order bit set, fold */
sum = (sum & 0xFFFF) + (sum >> 16);
len -= 2;
}
if(len) /* take care of left over byte */
sum += (unsigned short) *((unsigned char *)temp);
while(sum>>16)
sum = (sum & 0xFFFF) + (sum >> 16);
return ~sum;
}
int BindRawSocketToInterface(int rawsock, char *addr, short int port)
{
struct sockaddr_in s_addr;
s_addr.sin_family = AF_INET;
s_addr.sin_addr.s_addr = inet_addr(addr);
s_addr.sin_port = htons(port);
if((bind(rawsock, (struct sockaddr *)&s_addr, sizeof(s_addr)))== -1)
{
perror("Error binding raw socket to interface\n");
exit(-1);
}
return 1;
}
// Fabricate the IP header or we can use the
// standard header structures but assign our own values.
struct ip *CreateIPHeader(char *srcip, char *destip)
{
struct ip *ip_header;
ip_header = (struct ip *)malloc(sizeof(struct ip));
ip_header->ip_v = 4;
ip_header->ip_hl = 5;
ip_header->ip_tos = 0;
ip_header->ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + DATA_SIZE);
ip_header->ip_id = htons(111);
ip_header->ip_off = 0;
ip_header->ip_ttl = 111;
ip_header->ip_p = IPPROTO_UDP;
ip_header->ip_sum = 0; /* We will calculate the checksum later */
inet_pton(AF_INET, srcip, &ip_header->ip_src);
inet_pton(AF_INET, destip, &ip_header->ip_dst);
/* Calculate the IP checksum now :
The IP Checksum is only over the IP header */
ip_header->ip_sum = ComputeChecksum((unsigned char *)ip_header, ip_header->ip_hl*4);
return (ip_header);
}
// Creates a the UDP header.
struct udphdr *CreateUdpHeader(char *srcport, char *destport )
{
struct udphdr *udp_header;
/* Check netinet/udp.h for header definiation */
udp_header = (struct udphdr *)malloc(sizeof(struct udphdr));
udp_header->source = htons(atoi(srcport));
udp_header->dest = htons(atoi(destport));
udp_header->len = htons(sizeof(struct udphdr) + DATA_SIZE); //TODO: need to specify this
udp_header->check = htons(0);
return (udp_header);
}
void CreatePseudoHeaderAndComputeUdpChecksum(struct udphdr *udp_header, struct ip *ip_header, unsigned char *data)
{
/*The TCP Checksum is calculated over the PseudoHeader + TCP header +Data*/
/* Find the size of the TCP Header + Data */
int segment_len = ntohs(ip_header->ip_len) - ip_header->ip_hl*4;
/* Total length over which TCP checksum will be computed */
int header_len = sizeof(PseudoHeader) + segment_len;
/* Allocate the memory */
unsigned char *hdr = (unsigned char *)malloc(header_len);
/* Fill in the pseudo header first */
PseudoHeader *pseudo_header = (PseudoHeader *)hdr;
pseudo_header->source_ip = ip_header->ip_src.s_addr;
pseudo_header->dest_ip = ip_header->ip_dst.s_addr;
pseudo_header->reserved = 0;
pseudo_header->protocol = ip_header->ip_p;
pseudo_header->udp_length = htons(segment_len);
/* Now copy TCP */
memcpy((hdr + sizeof(PseudoHeader)), (void *)udp_header, 8);
/* Now copy the Data */
memcpy((hdr + sizeof(PseudoHeader) + 8), data, DATA_SIZE);
/* Calculate the Checksum */
udp_header->check = ComputeChecksum(hdr, header_len);
/* Free the PseudoHeader */
free(hdr);
}
// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
int sd, ix;
char buffer[PCKT_LEN];
char data[DATA_SIZE];
int one = 1;
char interface[100];
struct ifreq ifr;
time_t the_time;
// Source and destination addresses: IP and port
struct sockaddr_in to_addr;
const int *val = &one;
printf("IP Header Size: %u \n", sizeof(struct ip));
printf("UDP Header Size: %u \n", sizeof(struct udphdr));
printf("Data Size: %d\n", DATA_SIZE);
printf("IP Total: %u \n", sizeof(struct ip) + sizeof(struct udphdr) + DATA_SIZE);
memset(buffer, 0, PCKT_LEN);
if(argc != 5 && argc != 6)
{
printf("- Invalid parameters!!!\n");
printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port> [interface]\n", argv[0]);
exit(-1);
}
if (argc == 6)
strcpy(interface, argv[5]);
else
strcpy(interface, "eth0");
printf("Interface: %s\n", interface);
// bind() fails in BindRawSocketToInterface() above if it is passed a source address that
// is not the actual host sending (i.e. spoofing): "Cannot assign requested address"
#if 0
// Create a raw socket with UDP protocol
sd = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");
//Bind the socket to the source address and port.
BindRawSocketToInterface(sd, argv[1], atoi(argv[2]));
#else
sd = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket() - Using SOCK_RAW socket and RAW protocol is OK.\n");
memset (&ifr, 0, sizeof (ifr));
snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
if (ioctl(sd, SIOCGIFINDEX, &ifr))
{
perror("ioctl() error ");
exit(-1);
}
if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0)
{
perror("setsockopt() error (#2)");
exit(-1);
}
#endif
// Inform the kernel do not fill up the packet structure. we will build our own...
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(int)) < 0)
{
perror("setsockopt() error");
close(sd);
exit(-1);
}
else
printf("setsockopt() is OK.\n");
// The source is redundant, may be used later if needed
// The address family
to_addr.sin_family = AF_INET;
to_addr.sin_addr.s_addr = inet_addr(argv[3]);
to_addr.sin_port = htons(atoi(argv[4]));
//Create the IP header.
struct ip *ip_header = CreateIPHeader(argv[1], argv[3]);
//Create the UDP header.
struct udphdr *udp_header = CreateUdpHeader(argv[2], argv[4]);
printf("Using raw socket and UDP protocol\n");
printf("Using Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
// include a timestamp
memset(data, ' ', sizeof(data));
the_time = htonl(time(NULL));
memcpy(data, &the_time, sizeof(the_time));
//Compute UDP checksum
CreatePseudoHeaderAndComputeUdpChecksum(udp_header, ip_header, (unsigned char*)data);
for (ix = 0; ix < 1000000; ++ix)
{
//Copy IP header, UDP header, and data to the packet buffer.
memcpy(buffer, ip_header, sizeof(struct ip));
memcpy(buffer + sizeof(struct ip), udp_header, 8 /*sizeof(struct udphdr)*/);
memcpy(buffer + sizeof(struct ip) + 8, data, DATA_SIZE);
// length must include header sizes
#if 0
if(sendto(sd, buffer, 20/*ip_header->ip_len*/, 0, (struct sockaddr *)&to_addr, sizeof(to_addr)) < 0)
#else
if(sendto(sd, buffer, sizeof(struct ip) + sizeof(struct udphdr) + DATA_SIZE, 0,
(struct sockaddr *)&to_addr, sizeof(to_addr)) < 0)
#endif
{
perror("sendto() error");
break;
}
else
{
printf("sendto() is OK.\n");
}
sleep(1);
} // loop
free(ip_header);
free(udp_header);
close(sd);
return 0;
}

Raw socket not sending packets containing arbitrary data

Take the following code example
https://gist.github.com/3825444
/*
Testing arbitrary raw ip packets
works only if datagram is filled with 0
filling with anything else will not send any packets, or atleast wireshark does not detect anything
this is strange
*/
#include<stdio.h>
#include<string.h> //memset
#include<sys/socket.h>
#include<stdlib.h> //for exit(0);
#include<errno.h> //For errno - the error number
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
int main (void)
{
//Create a raw socket
int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
if(s < 0)
{
perror("socket");
}
//Datagram to represent the packet
char datagram[4096] , source_ip[32];
struct sockaddr_in sin;
strcpy(source_ip , "192.168.1.2");
sin.sin_family = AF_INET;
sin.sin_port = htons(80);
sin.sin_addr.s_addr = inet_addr ("1.2.3.4");
memset (datagram, 2 , 4096); /* zero out the buffer */
//IP_HDRINCL to tell the kernel that headers are included in the packet
int one = 1;
const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
{
printf ("Error setting IP_HDRINCL. Error number : %d . Error message : %s \n" , errno , strerror(errno));
exit(0);
}
//Uncommend the loop if you want to flood :)
while (1)
{
//Send the packet
if (sendto (s, /* our socket */
datagram, /* the buffer containing headers and data */
512, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof (sin)) < 0) /* a normal send() */
{
perror("sendto");
}
//Data send successfully
else
{
printf ("Packet Send \n");
}
}
return 0;
}
The above program does not generate any packets, or atleast wireshark will not detect any.
However if the datagram is filled with 0 by doing
memset (datagram, 0 , 4096); /* zero out the buffer */
then plenty of packets are generate and are detected by wireshark.
Why such a difference ?
You're putting garbage into the header. It's more remarkable that setting zeros succeeds than that setting 2's fails.

raw sockets in c - bogus header length

#include<stdlib.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#define P 5000 /* lets flood the port */
unsigned short /* this function generates header checksums */
csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int
main (void)
{
char ipp[10] = "1.2.3.4";
int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); /* open raw socket */
char datagram[4096]; /* 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 */
struct ip *iph = (struct ip *) datagram;
struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip);
struct sockaddr_in sin;
/* the sockaddr_in containing the dest. address is used
in sendto() to determine the datagrams path */
sin.sin_family = AF_INET;
sin.sin_port = htons (P);/* you byte-order >1byte header values to network
byte order (not needed on big endian machines) */
sin.sin_addr.s_addr = inet_addr ("192.168.1.12");
memset (datagram, 0, 4096); /* zero out the buffer */
/* we'll now fill in the ip/tcp header values, see above for explanations */
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr); /* no payload */
iph->ip_id = htonl (54321); /* the value doesn't matter here */
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0; /* set it to 0 before computing the actual checksum later */
iph->ip_src.s_addr = inet_addr (ipp);/* SYN's can be blindly spoofed */
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->source = htons (1234); /* arbitrary port */
tcph->dest = htons (P);
tcph->seq = random ();/* in a SYN packet, the sequence is a random */
tcph->ack_seq = 0;/* number, and the ack sequence is 0 in the 1st packet */
tcph->doff = 0; /* first and only tcp segment */
tcph->syn = 1;
tcph->window = htonl (65535); /* maximum allowed window size */
tcph->check = 0;/* if you set a checksum to zero, your kernel's IP stack
should fill in the correct checksum during transmission */
tcph->urg_ptr = 0;
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
/* finally, it is very advisable to do a IP_HDRINCL call, to make sure
that the kernel knows the header is included in the data, and doesn't
insert its own header into the packet before our data */
{ /* lets do it the ugly way.. */
int one = 1;
const int *val = &one;
if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
printf ("Warning: Cannot set HDRINCL!\n");
}
int i1=49;
char i2 = 49;
int cc = 0;
int r1;
while (cc<99)
{
ipp[6] = i1;
ipp[7] = i2;
if(i1 == 57)
{
break;
}
if(i2 == 57 )
{ i2 = 48;
i1++;
}
i2++;
cc++;
iph->ip_src.s_addr = inet_addr (ipp);
if (sendto (s, /* our socket */
datagram, /* the buffer containing headers and data */
iph->ip_len, /* total length of our datagram */
0, /* routing flags, normally always 0 */
(struct sockaddr *) &sin, /* socket addr, just like in */
sizeof (sin)) < 0) /* a normal send() */
printf ("error\n");
else
printf ("sent \n");
}
return 0;
}
the code creates a raw socket with proper ip address and the source addrewss is 192.168.1.12...port 5000 ... the problem is that when i try to capture the packets sent using wireshark, it says something like bogus tcp headee length...should be atleast 20 ... how can i correct this error ...
P.S. you can refer link for the code explanation if you find the code lengthy ...
After further reading: change this line
struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip);
to this
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip));
In the first case tcph would pointer far beyond iph.
char *datagramshould be unsigned char *too.

Raw socket NOT sending

I am trying to write a sample Raw socket program to clear my understanding of raw sockets. I create a Raw UDP socket and then call sendto. My sendto succeeds but I never see the packet received by the other side. I don't have any receive side running so I am relying on Wireshark running on both the sender and receiver.
I am pasting the code snippet here. Please point out any errors.
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include "protHeaders.x"
#include "gen.h"
U16 csum(U16* buf, S32 nwords)
{
U32 sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}/*csum*/
int main(int argc,char** argv)
{
U8 datagram[MAX_IPPACKET];
U8 udpPayLoad[MAX_UDPPAYLOAD];
CustIpHeader* ipH;
CustUdpHeader* udpH;
struct sockaddr_in sin;
S32 sockFd;
S32 one = 1;
const S32* val = &one;
ipH = (CustIpHeader *)datagram;
udpH = (CustUdpHeader *)(datagram + sizeof(CustIpHeader));
memset(datagram,0,sizeof(datagram));
memset(udpPayLoad,0,sizeof(udpPayLoad));
memset(&sin,0,sizeof(struct sockaddr_in));
strcpy(udpPayLoad,"<<<<Aditya>>>>");
sin.sin_family = AF_INET;
sin.sin_port = htons(atoi(argv[4]));
/* fill the Ip header */
ipH->ip_hl = 5;
ipH->ip_v = 4;
ipH->ip_tos = 0;
ipH->ip_len = sizeof(CustIpHeader) + sizeof(CustUdpHeader) + strlen(udpPayLoad);
ipH->ip_id = htonl(54321);
ipH->ip_off = 0;
ipH->ip_p = 17;
ipH->ip_ttl = 65;
ipH->ip_sum = 0;
ipH->ip_src.s_addr = inet_addr(argv[1]);
ipH->ip_dst.s_addr = inet_addr(argv[3]);
/* fill the Udp header */
udpH->uh_sport = htons(atoi(argv[2]));
udpH->uh_dport = htons(atoi(argv[4]));
udpH->uh_len = sizeof(CustUdpHeader) + strlen(udpPayLoad);
udpH->uh_check = 0;
printf("Checksum = %u\n",udpH->uh_check);
/* copy udpPayLoad */
strcpy(datagram+sizeof(CustIpHeader)+sizeof(CustUdpHeader),udpPayLoad);
#if 1
printf("Datagram %p,UdpPayload %p\n",(void *)datagram,(void *)datagram+sizeof(CustIpHeader)+sizeof(CustUdpHeader));
printf("IpHeader %p, UdpHeader %p\n",(void *)ipH,udpH);
#endif
/* fill in the checksum */
ipH->ip_sum = csum((U16 *)datagram,ipH->ip_len >> 1);
printf("Checksum = %u\n",ipH->ip_sum);
if ((sockFd = socket(PF_INET,SOCK_RAW,IPPROTO_UDP)) < 0)
{
perror("socket:create");
RETURN(RFAILED);
}
/* doing the IP_HDRINCL call */
if (setsockopt(sockFd,IPPROTO_IP,IP_HDRINCL,val,sizeof(one)) < 0)
{
perror("Client:setsockopt");
}
while(1)
{
if ( sendto(sockFd,
datagram,
ipH->ip_len,
0,
(struct sockaddr *)&sin,
sizeof (sin)) < 0)
{ perror("Client:sendto"); }
else
printf(".");
}
RETURN(ROK);
}
The IP and UDP headers are:
typedef struct _ipheader
{
U8 ip_hl:4,ip_v:4; /* ip_hl: the ip header length in 32bit octets.
* ip_v : ip version (always 4 for our case).
*/
U8 ip_tos; /* reliability of the service. 0x00 is Normal */
U16 ip_len; /* totoal length including ip header,icmp/tcp/udp header
* and payload size in bytes
*/
U16 ip_id; /* sequence no. used for reassembly of fragmented IP packets */
U16 ip_off; /* the fragment offset used for reassembly of fragmented packets */
U16 ip_p; /* the transport layer protocol. can be tcp (6), udp(17) */
U8 ip_ttl; /* time to live */
U16 ip_sum; /* the datagram checksum for the whole IP packet */
struct in_addr ip_src; /* the source IP address, converted to a long format */
struct in_addr ip_dst; /* the desitnation IP address, converted to a long format */
}CustIpHeader; /* total ip header length: 20 bytes */
typedef struct _udpheader
{
U16 uh_sport; /* The source port that a client bind()s to */
U16 uh_dport; /* The desination port that a server bind()s to*/
U16 uh_len; /* The length of udp header and payload data in bytes */
U16 uh_check; /* The checksum of header and data */
}CustUdpHeader; /* total udp header length: 8 bytes (=64 bits) */
I am running as root user, so privileges is not a problem.
Language: C
Os: Linux
I had the wireshark running on a slow system. The packets were indeed being send but the Wireshark could only show them after a gap of 6 minutes or so. Moving to a faster system helped. I am therefore closing this myself.
This may help you to get started http://www.securitytube.net/Raw-Sockets-Basics-Presentation-video.aspx.
if you are using libcap/wincap i would have helped. but above video help you get started.

Resources