Getting an ACK for RAW SYN packet

Hi,

I'm trying to create a RAW TCP SYN packet and send it from one Linux machine to another. I know the packet I have created is well formed and is received by the peer.

Now what I want is to get an ACK for my SYN. I want the peer's Network protocol stack to send me an ACK for that. I know RAW socket is not stream oriented, but is instead datagram-oriented. But can you tell me if there is any hack that I can use to get the network protocol stack to send back an ACK.

Thanks.

>How do you know this?
I know this, since when I do a revcfrom on the peer, I receive the exact no. of bytes I sent.. If my packet was malformed, I should have got an ICMP error message, which I don't.

>If your TCP segment was well-formed, then the peer should do this automatically. It >wouldn't be able to tell the difference between the raw socket you used and a >``normal'' socket anyway, so the same behavior can be expected. It is transparent ...
>Maybe you could post the code you're using if it isn't too long.[/b]
[/quote]

RAW sockets difer from stream sockets in the sense that the network protocol stack does not bother about packets coming from RAW sockets. Therefore, for the SYN on a RAW socket, it doen't return an SYN|ACK.

I will post my code once the remote machine is up.

>I can't see how this guarantees that your packet is ``well-formed''. Maybe we have differing definitions of ``well-formed'' on this issue, but I mean a packet with valid TCP >content too, not just the same number of bytes you sent out ...

On this issue, can you tell me if the packet is mal formed, will I receive an ICMP error? And if I do, how can I catch it ?

>It's not my fault if you do not mention that the server side uses a raw socket too. Why don't you run a normal server and see whether an ACK is generated? Running both sides with raw >sockets where you could use a stream socket on either side to >ease debugging is asking for trouble ...

Thanks I will try this and let you know what happens.

>Edit: May I ask what's the purpose of your applications?

The research we are doing involves mesuring the MTU from each hop to other. We are using an approach in which the Maximum Segment Size in TCP header can be used.

What you're attempting is so far "out there" that I hesitate to reply. I have never used raw sockets at all. And you seem to be trying to bypass TCP entirely. I'm not sure what to expect when raw sockets are used like that. Like Driver, I think it would help if you posted your code.

I do know the TCP protocol though. Your SYN packet seems to be step one of the 3-way handshake. If it's addressed to port that is listening, You should get a packet that ACK's your SYN and contains a SYN of it's own. Otherwise you should get a RST packet. These days, some systems run in stealth mode and just ignore SYN's to unused ports.

You should not get an ICMP message. But if you fumble a bit, and set the protocol to UDP instead on TCP, then a ICMP port unreachable would be in order.

But you're using raw sockets, right? So isn't all of this your job? You seem to be expecting the kernel's TCP code to help you out. I don't know if it should or not. Like I said, I've never used raw sockets like this. But my expectation would be that the kernel's TCP code would not be in use. After all, to the kernel, there is no TCP connection.

To answer your original question, you can use a raw socket on the client who sends the SYN, and a regular listening stream socket on the server to automatically reply with ACK.

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;
} * ip_header_t;

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;
} * tcp_header_t;

int readn(int, void *, int);

int main(int argc, char * argv[])
{
int sock,sent, temp, rcvd;
struct sockaddr_in sin;
unsigned short local_port;
unsigned short remote_port;
unsigned char protocol;
char * buffer;
//char data[1452];
ip_header_t ip_header;
tcp_header_t tcp_header;
char *remote_ip_str;
int semantics = 0;
unsigned short buffer_size = 0;
int tmp;

protocol = IPPROTO_TCP;
semantics = SOCK_RAW;

remote\_ip\_str=DEST\_IP_ADDR;
remote_port = 6666;

if\(\(sock = socket\(PF_INET, semantics, protocol\)\) < 0\) \{ 
	perror\("socket"\);
	exit\(1\);
\}

bzero\(\(char *\)& sin, sizeof\(sin\)\);
sin.sin_port = htons\(local_port\);

if \(\(bind\(sock, \(struct sockaddr *\)& sin, sizeof\(sin\)\)\) < 0\) \{
	perror\("bind"\);
	exit\(1\);
\}

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

bzero\(\(char *\)& sin, sizeof\(sin\)\);
sin.sin_family = AF_INET;
sin.sin_port = htons\(remote_port\);
sin.sin\_addr.s_addr = inet\_addr\(remote\_ip_str\);

buffer_size = sizeof\(struct ip\_header_t\) \+ sizeof\(struct tcp\_header_t\);

       srand\(getpid\(\)\);

buffer = \(char *\) malloc\(buffer_size\);

ip_header = \(ip\_header_t\) buffer;
ip_header->ihl = 5;
ip_header->version = 4;
ip_header->tos = 0;
ip\_header->tot_len = htons\(buffer_size\);
ip_header->id = 0;
ip_header->ttl = 64;
ip\_header->frag_off = 0x40;
ip_header->protocol = protocol;
ip_header->check = 0; 
ip_header->daddr = inet\_addr\(remote\_ip_str\);
ip_header->saddr = 0;

tcp_header = \(tcp\_header_t\) \(ip_header \+ 1\);

tcp_header->source = htons\(local_port\);
tcp_header->dest = htons\(remote_port\);
tcp_header->seq = rand\(\)%time\(NULL\);
tcp\_header->ack_seq = rand\(\)%time\(NULL\);
tcp_header->res1 = 0;
tcp_header->doff = 4;
tcp_header->syn = 1;
tcp_header->check = 0;

printf\("SEQ is %u\\n", tcp_header->seq\);
if\(\(sent=sendto\(sock, buffer, buffer_size, 0, \(struct sockaddr *\) &sin, 
				sizeof\(sin\)\)\) < buffer_size\) \{
	perror\("sendto"\);
	exit\(1\);
\}
printf\("Came here sent %d bytes \\n",sent\);
if\(\(rcvd = readn\(sock, buffer, buffer_size\)\) < 0 \) \{
	fprintf\(stderr, "nread error\\n"\);
\}
else
	printf\("Received %d bytes\\n", rcvd\);

close\(sock\);

return 0;

}

Can you please tell me what's wrong with the packet header I have created? I can't accept it using a STREAM socket. I think there is a problem with the header format, can you tell me what's that?

Thanks

Maybe the checksum field is incorrect and your packet gets discarded...

Thanks for the reply. Here is the complete code, with all the includes and accessory functions.

This code compiles on Linux machines on which I'm working.

I can't use struct tcphdr and iphdr, since I have to manipulate the options in the tcp header. That's the whole purpose of this struggle.

Thanks.

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/time.h>/* struct timeval */
#include <unistd.h>
#include <string.h>
#include <time.h>

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;
} * ip_header_t;

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;
} * tcp_header_t;

int readn(int, void *, int);

int main(int argc, char * argv[])
{
int sock,sent, temp, rcvd;
struct sockaddr_in sin;
unsigned short local_port;
unsigned short remote_port;
unsigned char protocol;
char * buffer;
//char data[1452];
ip_header_t ip_header;
tcp_header_t tcp_header;
char *remote_ip_str;
int semantics = 0;
unsigned short buffer_size = 0;
int tmp;

protocol = IPPROTO_TCP;
semantics = SOCK_RAW;

//data = \(char *\)calloc\(1452, 1\); 
//printf\( "Data is %d\\n", sizeof\(data\)\);
remote\_ip\_str=DEST\_IP_ADDR
local_port = 6666;
remote_port = 6666;

if\(\(sock = socket\(PF_INET, semantics, protocol\)\) &lt; 0\) \{ 
	perror\("socket"\);
	exit\(1\);
\}

bzero\(\(char *\)& sin, sizeof\(sin\)\);
sin.sin_port = htons\(local_port\);

if \(\(bind\(sock, \(struct sockaddr *\)& sin, sizeof\(sin\)\)\) &lt; 0\) \{
	perror\("bind"\);
	exit\(1\);
\}

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

bzero\(\(char *\)& sin, sizeof\(sin\)\);
sin.sin_family = AF_INET;
sin.sin_port = htons\(remote_port\);
sin.sin\_addr.s_addr = inet\_addr\(remote\_ip_str\);


/*
   buffer_size = sizeof\(struct ip\_header_t\) \+ sizeof\(struct tcp\_header_t\)
   \+ sizeof\(data\);
 */
buffer_size = sizeof\(struct ip\_header_t\) \+ sizeof\(struct tcp\_header_t\);
//buffer_size = sizeof \(struct ip\_header_t\) \+ sizeof\(data\);

printf\("buff %d\\n", buffer_size\);

srand\(getpid\(\)\);

buffer = \(char *\) malloc\(buffer_size\);

ip_header = \(ip\_header_t\) buffer;
ip_header-&gt;ihl = 5;
ip_header-&gt;version = 4;
ip_header-&gt;tos = 0;
ip\_header-&gt;tot_len = htons\(buffer_size\);
ip_header-&gt;id = 0;
ip_header-&gt;ttl = 64;
ip\_header-&gt;frag_off = 0x40;
ip_header-&gt;protocol = protocol;
ip_header-&gt;check = 0; 
ip_header-&gt;daddr = inet\_addr\(remote\_ip_str\);
ip_header-&gt;saddr = 0;

tcp_header = \(tcp\_header_t\) \(ip_header \+ 1\);

tcp_header-&gt;source = htons\(local_port\);
tcp_header-&gt;dest = htons\(remote_port\);
tcp_header-&gt;seq = rand\(\)%time\(NULL\);
tcp\_header-&gt;ack_seq = rand\(\)%time\(NULL\);
tcp_header-&gt;res1 = 0;
tcp_header-&gt;doff = 4;
tcp_header-&gt;syn = 1;
tcp_header-&gt;check = 0;

printf\("SEQ is %u\\n", tcp_header-&gt;seq\);
if\(\(sent=sendto\(sock, buffer, buffer_size, 0, \(struct sockaddr *\) &sin, 
				sizeof\(sin\)\)\) &lt; buffer_size\) \{
	perror\("sendto"\);
	exit\(1\);
\}
printf\("Came here sent %d bytes \\n",sent\);
if\(\(rcvd = readn\(sock, buffer, buffer_size\)\) &lt; 0 \) \{
	fprintf\(stderr, "nread error\\n"\);
\}
else
	printf\("Received %d bytes\\n", rcvd\);

close\(sock\);

return 0;

}

/* R E A D N
Reads N byted from the discriptor
*/

int readn(int fd, void *vptr, int n)
{
size_t nleft;
ssize_t nread;
char *ptr;

ptr = vptr;
nleft = n;
while \(nleft &gt; 0\) \{
	printf\( "Nleft is %d\\n", nleft\);
	if \(\(nread = read\(fd, ptr, nleft\)\) &lt; 0\) \{
		if \(errno == EINTR\)
			nread = 0;		/* and call read\(\) again */
		else
			return\(-1\);
	\} else if \(nread == 0\)
		break;				/* EOF */

	nleft -= nread;
	ptr   \+= nread;
\}
return\(n - nleft\);		/* return &gt;= 0 */

}

/* tcp_header->check = 0; */
While working on it very long time ago, i found out i cannot let the kernel compute tcp checksum for me... at least on a k2.0 series :slight_smile:

Make sure you have the correct checksum in tcp hdr that is compute it yourself, You will have to create a pseudo-header only for that puspose

I'm looking for my old archives and i'll post the checksum portion if you want

BTW, trying to implement a DoS or man-in-the-middle attack ??? :slight_smile:

Andryk, thanks for your reply.

Please post the checksum portion of the pseudo header.

Haha, I'm not trying to implement anything like DoS or Man-in-the-middle, but if happens accidenly, I won't mind ;).

Thanks.

Here it is, the trick is to correctly build the pseudo hdr (struct cksum) and then run the cksum algo. on it.
I ran my test on loopback as there are less output ...
-------------------------------------------
struct cksum {
unsigned int src_addr; /* source from ip hdr /
unsigned int dst_addr; /
dest from ip hdr /
unsigned char placeholder; /
this is for memory displacement */
unsigned char protocol;
unsigned short pr_length;

struct   tcphdr  tcp;            
 
char		buf[4096];     /* Any size your packet data needs */ 

};

-----------------------------------------------------
...
char pkt; / ptr to begin of packet buffer */
struct iphdr *ip;
struct tcphdr *tcp;
char *dta;

struct cksum _cksum;
unsigned short cksum = 0;

ip = (struct iphdr *)pkt;
tcp = (struct tcphdr *)(pkt + (ip->ihl << 2));

/* building pseudo header */
bzero( (char )&_cksum, sizeof(struct cksum) );
_cksum.src_addr = ip->saddr;
_cksum.dst_addr = ip->daddr;
_cksum.protocol = IPPROTO_TCP;
_cksum.pr_length = htons( ntohs(ip->tot_len) - (ip->ihl<<2) );
tcp->check = 0;
bcopy( tcp, &_cksum.tcp, 20 ); /
sizeof tcp hdr */

/* Any data following tcp hdr to be checksummed */
dta = (char *) (pkt + (ip->ihl<<2) + (tcp->doff<<2) );
bcopy( dta, _cksum.buf, ntohs(ip->tot_len) - (ip->ihl<<2) - (tcp->doff<<2) );

/* compute 16-bits tcp checksum */
cksum = in_cksum( (unsigned short *)&_cksum, 12 + ntohs(ip->tot_len) - (ip->ihl<<2) );
return cksum;
...
------------------------------------------------------
unsigned short in_cksum( unsigned short addr, int len ) {
int nleft = len;
int sum = 0; /
32-bit */

unsigned short w = addr;
unsigned short answer = 0; /
16-bit */

/* Our algorithm is simple, using 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) {
*(unsigned char *) (&answer) = *(unsigned char ) w;
sum += answer;
}
/
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);
}

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 &gt; 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 &gt;&gt; 16\) \+ \(sum & 0xffff\);/* add high-16 to low-16 */
sum \+= \(sum &gt;&gt; 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\)\)\) &lt; 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-&gt;ihl = 5;
ip-&gt;version = 4;
ip-&gt;tos = 0;
ip-&gt;tot_len = htons\(sizeof\(struct ip\_header_t\)\+sizeof\(struct tcp\_header_t\)\);
ip-&gt;id = 0;
ip-&gt;ttl = 64;
ip-&gt;frag_off = 0x40;
ip-&gt;protocol = IPPROTO_TCP;
ip-&gt;check = in_cksum\( \(u_short *\)ip, sizeof\( struct ip\_header_t\)\);
ip-&gt;daddr = dstaddr;
ip-&gt;saddr = srcaddr;

pseudo-&gt;saddr = srcaddr;
pseudo-&gt;daddr = dstaddr;
pseudo-&gt;zero = 0;
pseudo-&gt;protocol = IPPROTO_TCP;
pseudo-&gt;length = htons\(ntohs\(ip-&gt;tot_len\)-\(ip-&gt;ihl&lt;&lt;2\)\);

tcp = \(tcphdr\) \(packet \+ \(ip-&gt;ihl &lt;&lt; 2\)\); 
tcp-&gt;source = htons\(local_port\);
tcp-&gt;dest = htons\(remote_port\);
tcp-&gt;seq = rand\(\)%time\(NULL\);
tcp-&gt;ack_seq = rand\(\)%time\(NULL\);
tcp-&gt;res1 = 0;
tcp-&gt;doff = 4;
tcp-&gt;syn = 1;
tcp-&gt;check = 0;

bcopy\(tcp, &pseudo-&gt;tcp, sizeof\(struct tcp\_header_t\)\);
tcp-&gt;check = in_cksum\(\(unsigned short *\)&pseudo, 
						12 \+ sizeof\(struct tcp\_header_t\)\);
       if\(\(sendto\(s, packet, sizeof\(packet\), 0,
		\(struct sockaddr *\) &foo,sizeof\(foo\)\)\) &lt; 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\)\)&lt;0\) \{
	perror\("RawSocket:"\);
	exit\(1\);
\}

if \(setsockopt\(rawfd,IPPROTO\_IP,IP_HDRINCL,&one,sizeof\(one\)\)&lt;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;

}

Shouldn't you fill in the src/dst addresses of your iphdr BEFORE calculating its checksum?

Even after that, the problem remains.

Here is a sample code that may help u!
Most kernel support syn-cookies to prevent synflood attack...

Wow could not attach the file, leave an email for delivery

Which compiler are you using, BTW? Sorry, I've been away. Did you mention the compiler? GCC?

Neo

Yes. I'm using gcc.

Btw, I'm getting a very strange error with sendto. Here's my code. I have compiled it with gcc and I get error :

sendto:invalid argument.

int main(int argc, char argv[])
{
struct pseudohdr {
unsigned long saddr; /
source address /
unsigned long daddr; /
dest address /
char zer0; /
zero /
unsigned char protocol; /
protocol to use /
unsigned short length; /
length of packet */
};

int one = 1, sent;
int packSize=sizeof(struct tcphdr)+sizeof(struct iphdr)
+sizeof(struct pseudohdr);
char packet[packSize]; /* Packet. /
struct sockaddr_in sin; /
Our address info structures. */
struct iphdr *ip = (struct iphdr *) packet;
struct tcphdr *tcp = (struct tcphdr *) packet + sizeof(struct iphdr);
struct pseudohdr *pseudo;
pseudo = (struct pseudohdr *) (packet + sizeof(struct iphdr) -
sizeof(struct pseudohdr));
char *remote_ip_str="128.112.139.72";

/* create the socket. /
if((sock = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) == -1) {
perror("socket"); /
Error creating socket. */
exit(-1);
}

bzero((char *) &sin, sizeof(sin));
sin.sin_port = htons(MYPORT);

if ((bind(sock, (struct sockaddr *)& sin, sizeof(sin))) < 0) {
perror("bind");
exit(1);
}

/* Tell the kernel we'll fill in the IP headers

  • outselves. */
    if((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one))) < 0 )
    {
    perror("setsockopt");
    exit(1);
    }

/* Fill in the destination info. */
bzero((char *)& sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(MYPORT);
sin.sin_addr.s_addr = inet_addr(remote_ip_str);

bzero(packet, sizeof(packet));

/* fill in the pseudo header - this is needed to help calculate

  • the checksum for the tcp segment of the packet. */
    pseudo->saddr = 0;
    pseudo->daddr = (u_long)inet_ntoa(sin.sin_addr);
    pseudo->zer0 = 0;
    pseudo->protocol = IPPROTO_TCP;
    pseudo->length = htons(sizeof(struct tcphdr));

/* Fill in IP headers. /
ip->ihl = 5;
ip->version = 4;
ip->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);
ip->id = htons(0);
ip->saddr = 0;
ip->daddr = (u_long)inet_ntoa(sin.sin_addr);
ip->ttl = 64;
ip->protocol = IPPROTO_TCP;
ip->check = 0; /
calculate checksum later, below. /
ip->tos = 0;
ip->frag_off = 0;
/
set the checksum. */
ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr));

/* Fill in the TCP headers. */
tcp->source = htons(MYPORT);
tcp->dest = htons(MYPORT);

tcp->seq = htons(random()); /* "random" sequence number. /
tcp->ack = 0; /
ACKnowledgement /
tcp->syn = 1;
tcp->window = htons(65535);
tcp->doff = 5;
tcp->rst = 0;
tcp->check = 0; /
calculate checksum later, below. /
tcp->psh = 0;
tcp->fin = 0;
tcp->urg = 0;
tcp->ack_seq = htons(0);
/
set the checksum. */
tcp->check = (unsigned short)in_cksum((unsigned short *)pseudo,
sizeof(struct tcphdr)+sizeof(struct pseudohdr));

//if((sent=sendto(sock, packet, ip->tot_len, 0, This didn't work either.
if((sent=sendto(sock, packet, sizeof(packet), 0,
(struct sockaddr *)&sin, sizeof(sin))) < 0 ) {
printf("sent is %d\n", sent);
perror("sendto");
exit(1);
}
printf("sent is %d\n", sent);
return(0);
}

unsigned short in_cksum(unsigned short *addr, int len) {
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;

while (nleft > 1) {
sum += *w++;
nleft -= 2;
}

if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}

sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer); /* return the checksum value. */
}