Can you tell me what's the problem in this code of mine. I have used your checksum code. I'm not entirely sure, if it's correct or not.
Thanks.
#include<stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MYPORT 6666
typedef struct ip_header_t {
unsigned char ihl:4,
version:4;
unsigned char tos;
unsigned short tot_len;
unsigned short id;
unsigned short frag_off;
unsigned char ttl;
unsigned char protocol;
unsigned short check;
unsigned int saddr;
unsigned int daddr;
} *iphdr;
typedef struct tcp_header_t {
unsigned short source;
unsigned short dest;
unsigned int seq;
unsigned int ack_seq;
unsigned short res1:4,
doff:4,
fin:1,
syn:1,
rst:1,
psh:1,
ack:1,
urg:1,
ece:1,
cwr:1;
unsigned short window;
unsigned short check;
unsigned short urg_ptr;
} *tcphdr;
struct pseudo {
u_long saddr;
u_long daddr;
u_char zero;
u_char protocol;
u_short length;
struct tcp_header_t tcp;
};
/* Calculate the checksum here */
unsigned short in_cksum (unsigned short *ptr, int nbytes) {
register long sum;/* assumes long == 32 bits */
u_short oddbyte;
register u_short answer;/* assumes u_short == 16 bits */
/*
* 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.
*/
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
/* mop up an odd byte, if necessary */
if (nbytes == 1) {
oddbyte = 0;/* make sure top half is zero */
*((u_char *) & oddbyte) = *(u_char *) ptr;/* one byte only */
sum += oddbyte;
}
/*
* Add back carry outs from top 16 bits to low 16 bits.
*/
sum = (sum >> 16) + (sum & 0xffff);/* add high-16 to low-16 */
sum += (sum >> 16);/* add carry */
answer = ~sum;/* ones-complement, then truncate to 16 bits */
return (answer);
}
int sendpack( int s, u_long srcaddr, u_short srcport, u_long dstaddr, u_short dstport, u_long length)
{
int one=1;
unsigned short local_port, remote_port;
u_char packet[sizeof(struct ip_header_t)
+ sizeof(struct pseudo) + sizeof(struct tcp_header_t)];
struct sockaddr_in foo;
struct in_addr srcinaddr,dstinaddr;
iphdr ip = (iphdr) packet;
struct pseudo *pseudo = (struct pseudo *)(packet+ sizeof(struct ip_header_t)
+sizeof(struct tcp_header_t));
//tcphdr tcp = (tcphdr) (packet + sizeof(struct ip_header_t)
// + sizeof(struct pseudo));
tcphdr tcp;
//bzero((char *)&pseudo, sizeof(struct pseudo));
bzero(packet, sizeof(packet));
foo.sin_port = htons(srcport);
/* I have to bind the RAW socket to a local port. It's required here */
if ((bind(s, (struct sockaddr *)& foo, sizeof(foo))) < 0) {
perror("bind");
exit(1);
}
setsockopt(s, 0, IP_HDRINCL, &one, sizeof(one));
bzero((char *)&foo,sizeof(foo));
foo.sin_family = AF_INET;
foo.sin_port = htons(remote_port);
foo.sin_addr.s_addr=dstaddr;
/* building packets */
ip->ihl = 5;
ip->version = 4;
ip->tos = 0;
ip->tot_len = htons(sizeof(struct ip_header_t)+sizeof(struct tcp_header_t));
ip->id = 0;
ip->ttl = 64;
ip->frag_off = 0x40;
ip->protocol = IPPROTO_TCP;
ip->check = in_cksum( (u_short *)ip, sizeof( struct ip_header_t));
ip->daddr = dstaddr;
ip->saddr = srcaddr;
pseudo->saddr = srcaddr;
pseudo->daddr = dstaddr;
pseudo->zero = 0;
pseudo->protocol = IPPROTO_TCP;
pseudo->length = htons(ntohs(ip->tot_len)-(ip->ihl<<2));
tcp = (tcphdr) (packet + (ip->ihl << 2));
tcp->source = htons(local_port);
tcp->dest = htons(remote_port);
tcp->seq = rand()%time(NULL);
tcp->ack_seq = rand()%time(NULL);
tcp->res1 = 0;
tcp->doff = 4;
tcp->syn = 1;
tcp->check = 0;
bcopy(tcp, &pseudo->tcp, sizeof(struct tcp_header_t));
tcp->check = in_cksum((unsigned short *)&pseudo,
12 + sizeof(struct tcp_header_t));
if((sendto(s, packet, sizeof(packet), 0,
(struct sockaddr *) &foo,sizeof(foo))) < sizeof(packet)) {
perror("sendto");
exit(1);
}
printf("Sent packet of size %d\n", sizeof(packet));
return 0;
}
u_long resolve_name(char *hostname) {
struct hostent *host;
u_long addr;
if ((addr = inet_addr(hostname)) != -1) return addr;
if ((host = gethostbyname(hostname)) == NULL) {
fprintf(stderr,"Can not resolve name: %s\n",hostname);
exit(1);
}
bcopy(host->h_addr,&addr,host->h_length);
return addr;
}
int main(argc,argv)
int argc;
char **argv;
{
int rawfd;
int one=1;
struct in_addr srcip,dstip;
u_short srcport,dstport;
srcip.s_addr=resolve_name("source name");
srcport=MYPORT;
dstip.s_addr=resolve_name("dest name");
dstport=MYPORT;
if ((rawfd=socket(PF_INET,SOCK_RAW,IPPROTO_TCP))<0) {
perror("RawSocket:");
exit(1);
}
if (setsockopt(rawfd,IPPROTO_IP,IP_HDRINCL,&one,sizeof(one))<0) {
perror("SetSockOpt:");
close(rawfd);
exit(1);
}
printf("sending packet from: %s:%i ",inet_ntoa(srcip),srcport);
printf("to %s:%i\n",inet_ntoa(dstip),dstport);
sendpack(rawfd,srcip.s_addr,srcport,dstip.s_addr,dstport,0);
close(rawfd);
return 0;
}