|
Hi, everyone!
I have written a small program which can send SYN TCP package.
The trouble I met with is when using 1.2.3.4 as source address
and using 2.3.4.5 as desrination address, all procudure works
OK. I have used Ethereal to sniffer the sending out packages.
But when I change the address to the real address of the LAN of
our lab. Strange packages are sent. They are ARP packages.
For example, when I change source address to 210.73.46.75 and
destination address to 210.73.46.82. Ethereal reports to me
a ARP package is sent, which means "who has 210.73.46.82? Tell
210.73.46.75".
How to use real network address to send a SYN TCP package?
Here is all of my source codes.
Source codes:
--------
/********************** main.c source file ************************/
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
struct tcpheader {
unsigned short int th_sport;
unsigned short int th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_x2:4, th_off:4;
unsigned char th_flags;
unsigned short int th_win;
unsigned short int th_sum;
unsigned short int th_urp;
}; /* total tcp header length: 20 bytes (=160 bits) */
struct ipheader {
unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
}; /* total ip header length: 20 bytes (=160 bits) */
typedef struct ps_hdr
{
unsigned int source_address; // Source Address => 4 Bytes
unsigned int dest_address; // Destination Address => 4 Bytes
unsigned char placeholder; // Place Holder => 1 Bytes
unsigned char protocol; // Protocol => 1 Bytes
unsigned short tcp_length; // TCP Length => + 2 Bytes
// = 12 Bytes
struct tcpheader tcp;
}PS_HDR;
// IP/TCP/UDP Checksum Function
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
#define PORT 25
int main (void)
{
WSADATA wsd;
char datagram[4096];
int bOpt = 1;
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}
// Create a raw socket
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d\n", WSAGetLastError());
return -1;
}
struct ipheader *iph = (struct ipheader *) datagram;
//struct tcpheader *tcph = (struct tcpheader *) datagram + sizeof (struct ipheader);
struct tcpheader *tcph = (struct tcpheader *) (datagram + sizeof (struct ipheader));
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons (PORT);
sin.sin_addr.s_addr = inet_addr ("210.73.46.82");
memset (datagram, 0, 4096); /* zero out the buffer */
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof (struct ipheader) + sizeof (struct tcpheader);
iph->ip_id = 1;
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0;
iph->ip_src = inet_addr ("210.73.46.75");
iph->ip_dst = sin.sin_addr.s_addr;
tcph->th_sport = htons (1234);
tcph->th_dport = htons (PORT);
tcph->th_seq = rand();
tcph->th_ack = 0;
tcph->th_x2 = 0;
tcph->th_off = 5;
tcph->th_flags = 2; // SYN
tcph->th_win = htons(65535);
tcph->th_sum = 0;
tcph->th_urp = 0;
iph->ip_sum = checksum((unsigned short *)&iph, sizeof(ipheader));
struct ps_hdr pseudo_header;
pseudo_header.source_address = inet_addr ("210.73.46.75");
pseudo_header.dest_address = sin.sin_addr.s_addr;
pseudo_header.placeholder = 0;
pseudo_header.protocol = 6;
pseudo_header.tcp_length = htons(20);
pseudo_header.tcp = *tcph;
tcph->th_sum = checksum ((unsigned short *)(&pseudo_header), 32);
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)) == SOCKET_ERROR)
{
printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
return -1;
}
while (1)
{
// Send The Packet
if (sendto(s, datagram, 40, 0, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("sendto() failed: %d\n", WSAGetLastError());
return -1;
}
}
return 0;
}
/********************** main.c source file ************************/
--------
Thanks in advance,
George
|
|
|
|
|
Hi,
maybe I didn't get it correctly from your description and having no time to test your code, so I hope that I am answering your question .
It goes that way, than when you want to sent some packets from src: 210.73.46.75 to dst: 210.73.46.82, the IP stack needs to know the Ethernet address of the destination card, because it must be filled to the ethernet frame, which will be send.
Therefore the 210.73.46.75 sends ARP packet with a query:
"who has 210.73.46.82? Tell
210.73.46.75".
Then the computer, which have IP 210.73.46.82 will send back his ethernet address, using ARP reply. And then the 210.73.46.75 can finally send the ethernet frame containing your IP packet.
I hope, that this is what you asked and that it cleared the sense of ARP packets as well. If you have some another/additional questions, just ask.
|
|
|
|
|
Thanks, geo_m buddy!
I do not understand why when I use virtual network address
"1.2.3.4" and "3.4.5.6", it works fine. I have used Ethereal
to sniffer and no ARP packages are sent.
So, I want to know why when using virtual network address, no
ARP packages are sent.
Can you help?
regards,
George
|
|
|
|
|
Don't know what happened exactly in your configuration, but I'll try to go deeper in that - the ARP packets are not send in a situation, when the computer is able to fill the correct ethernet address itself. This can happen' in two cases
1. the ARP result is in a cache (because the results are cached)
2. it is for the same computer (some derivate of 1. - computer knows his own ethernet address, so there is no need to ask through ARP)
You can look to content of your arp cache using command arp -a
Here you will probably see the default gateway for your computer and it's ethernet address. And I think this is also a key for answering your question - as the address 1.2.3.4 is correct internet address, and it is not in your subnet, your computes asks default gateway for processing the packet - it is simply forwarded to default gateway. And because default gateway was probably used before, the ARP result is taken from cache - no need for sending ARP packets.
You can play with arp command, and you can try to delete the content of the cache and see what's happened in what situation. Don't worry clearing the arp cache is harmless operation
|
|
|
|
|
Thanks, geo_m buddy!
I want to do things like this. Implement TCP three time shake
hands procedure on Windows system. Such is, Site A send a SYN
and then Site B send ACK_SYN, and finally site A send back ACK.
I want to know is it possible to do the job on Windows platform?
What the trouble I met is, I do not know how to send a TCP package
including special fields.
I want to use bind-accept mechanism to implement this. But I do not
know how to send back a TCP package with special field. For example,
flags field (where I can set SYN, ACK_SYN and ACK fields, etc).
I want to learn your advice about my work.
regards,
George
|
|
|
|
|
Hi,
difficult to say, I never worked with RAW_PACKETs or what is it, I worked only with really _raw_ packets But I think, it is possible to do it on WinNT. Question is only, why? The TCP is already implemented and works... So if there is no special reason for doing it with this hard way, I'd suggest to stick with proven solutions and stay on normal winsock. Or if it is just a toy project, it is a great way how to learn the internals of the TCP/IP (a bit too much coding for me, but why not, if you enjoy it :P )
Anyway, I looked to your sample, and I think the answer is quite easy - for ACK, FIN, PUSH, RST, SYN, URG flags, you have to simply set the th_flags member of your tcpheader structure, exactly as you are setting the SYN flag now.
The values for flags are defined as follows:
#define TCP_FLAG_URGENT 0x20<br />
#define TCP_FLAG_ACK 0x10<br />
#define TCP_FLAG_PUSH 0x08<br />
#define TCP_FLAG_RESET 0x04<br />
#define TCP_FLAG_SYN 0x02<br />
#define TCP_FLAG_FIN 0x01
so if you want to set two flags, you can simply do it by or-ing them. Then instead of:
tcph->th_flags = 2; // SYN
write something like:
tcph->th_flags = TCP_FLAG_ACK + TCP_FLAG_SYN; // Set ACK and SYN together
Let's go to the next step
|
|
|
|
|
Thanks, geo_m buddy!
I have written a simple program to send SYN. It works good when the target machine port number is 25 (SMTP). But when I change the port number to 5678
(you can see this statement #define PORT 5678 from the source code), I find the target machine automatically sending back a RST ACK package.
I do not want this to happen. For I want to simulate TCP's three time shake hands procudure. If the target machine sending back the package automatically for me, I will have no work to do.
How can I disable the RST ACK package sending by the target machine? Can you help?
I have a snapshot of Ethereal which recording the communication procedures.
If you want it, I can send it to you. For I do not know how to post an attachment of the post.
Here are the source code:
--------
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
struct tcpheader {
unsigned short int th_sport;
unsigned short int th_dport;
unsigned int th_seq;
unsigned int th_ack;
unsigned char th_x2:4, th_off:4;
unsigned char th_flags;
unsigned short int th_win;
unsigned short int th_sum;
unsigned short int th_urp;
}; /* total tcp header length: 20 bytes (=160 bits) */
struct ipheader {
unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
}; /* total ip header length: 20 bytes (=160 bits) */
struct ps_hdr
{
unsigned int source_address; // Source Address => 4 Bytes
unsigned int dest_address; // Destination Address => 4 Bytes
unsigned char placeholder; // Place Holder => 1 Bytes
unsigned char protocol; // Protocol => 1 Bytes
unsigned short tcp_length; // TCP Length => + 2 Bytes
// = 12 Bytes
struct tcpheader tcp;
};
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}
#define PORT 5678
int main (void)
{
WSADATA wsd;
char datagram[4096];
int bOpt = 1;
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}
// Create a raw socket
SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d\n", WSAGetLastError());
return -1;
}
struct ipheader *iph = (struct ipheader *) datagram;
struct tcpheader *tcph = (struct tcpheader *) (datagram + sizeof (struct ipheader));
struct ps_hdr *pseudo_header = (struct ps_hdr *) (datagram + 8);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons (PORT);
sin.sin_addr.s_addr = inet_addr ("210.73.46.79"); // TARGET ADDRESS MAKE SURE IT DOES EXIST
memset (datagram, 0, 4096); /* zero out the buffer */
pseudo_header->source_address = inet_addr ("210.73.46.75"); // YOUR ADDRESS, CAN BE SPOOFED
pseudo_header->dest_address = sin.sin_addr.s_addr;
pseudo_header->placeholder = 0;
pseudo_header->protocol = 6;
pseudo_header->tcp_length = htons(20);
tcph->th_sport = htons (1234);
tcph->th_dport = htons (PORT);
tcph->th_seq = rand();
tcph->th_ack = 0;
tcph->th_x2 = 0;
tcph->th_off = 5;
tcph->th_flags = 2; // SYN
tcph->th_win = htons(65535);
tcph->th_sum = 0;
tcph->th_urp = 0;
tcph->th_sum = checksum((unsigned short *) (datagram + 8), 32);
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = htons(40);
iph->ip_id = 1;
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0;
iph->ip_src = inet_addr ("210.73.46.75"); // YOUR ADDRESS, CAN BE SPOOFED
iph->ip_dst = sin.sin_addr.s_addr;
iph->ip_sum = checksum((unsigned short *) datagram, 20);
if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)) == SOCKET_ERROR)
{
printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
return -1;
}
//while (1)
//{
// Send The Packet
if (sendto(s, datagram, 40, 0, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("sendto() failed: %d\n", WSAGetLastError());
return -1;
}
//}
return 0;
}
--------
regards,
George
|
|
|
|
|
Is there some service/daemon/another program listening on the machine you are sending tye SYN packet to?
I assume, on that machine some mailserver is running and he responds to your request n port 25, but on port 5678 is nothing and therefore the OS refuses you the connection.
You need to have here some listening peer - you can write such a simple app from a scratch, just create socket, bind it to some address and start listening on the 5678 port. Then run it on the remote machine.
On the remote machine you can also run netstat -a -n and you will see on which ports someone is sitting and listening.
The ports marked as LISTENING are available for new incoming connections, on any other port you'll be refused - this is defined behavior.
good luck
|
|
|
|
|
Thanks, geo_m buddy!
I have made a test. When there is no process binding the port on the destination machine, after sending a SYN package from the source machine to the destination machine, the destination machine will send back a RST ACK package.
Then I write a simple TCP server to bind to a specific port on the destination machine. I found out that after sending a SYN package from the source machine to the destination machine, the destination machine will automatically send back a SYN ACK package.
Since I want to implement the three time shake hands myself, I do not want either cases happen. I just want to send a SYN package and do not want the destination machine to send back anything.
But I do not know how to do that. Can you help?
regards,
George
|
|
|
|
|
Hmm, if you want to implement the standard TCP handshake, I would first leave the server (remote machine) running standard IP stack and make my client to be fully running & compatible with.
In a next step I would make the server part communicating with standard TCP client (e.g. Telnet.exe). As a last step I'd put my client and my server together, and in this step it should work like a charm
To achieve the customized server-side, you have to develop the server using the probably raw_sockets also. There you will get your packet and you will make your response to it as well. But I'd keep that for a second step.
|
|
|
|
|
Thanks, geo_m buddy!
Your reply is a good road for me. Maybe a long way,
But the trouble I met with is how to disable the server
sending back anything. Because if the server automatically
sent back anything, all of my work is nonsense.
My plan is like this, client sends SYN to server. And at the
server side, I will start a process to sniffer. When the sniffer
process noticed the SYN package comes, it will start another process
to send back ACK SYN package. Is my plan feasible?
regards,
George
|
|
|
|
|
There I am on unstable grounds with the raw socket implementation on w2k :P
In general, where there is no listening socket at all, the OS should return RST to you. If there is a listener, he can either accept your connection (ACK ) or also refuse it (RST ), or just don't respond at all and you will timeouted.
The problem of your plan I can see in a fact, that meanwhile the sniffer will start new process etc, the OS will reply with the RST , because there will be no associated socket with the port specified. But there's a point of my raw winsock ignorance - maybe it is possible to listen with some raw socket on some specific port - this can be a solution for you, I don't know, I worked with TCP/IP either on a lowest level (next to ethernet), or using the std sockets, therefore the lack of knowledge in case of concrete raw socket configuration.
But maybe I don't understand your plan correctly - you want to have some sort of application on a server, which will return SYN ,ACK to your SYN request - but this is what the normal socket app. will do for you (as well as the smtp server already did), or where is the difference?
|
|
|
|
|
Thanks, geo_m buddy!
quote:
> or just don't respond at all and you will timeouted.
geo_m, I think if I can implement this and I will work out
my solution. Do you know how to let a client timeout? I think
I can set the timeout value to a large value to serve my purpose.
(Just let the client wait ACK SYN, and I will send back my own ACK SYN
from my another thread.) Is that feasible? Can this be easily done on Windows 2k platform?
quote:
> But maybe I don't understand your plan correctly - you want to have some >sort of application on a server, which will return SYN,ACK to your SYN ?>request - but this is what the normal socket app. will do for you (as well >as the smtp server already did), or where is the difference?
Yes, you are correct, geo_m. I just want to implement it myself. Just for learning purpose. Because I am interested in TCP three time shake hands communication.
Hope you can give me further help.
regards,
George
|
|
|
|
|
Hi,
I just discussed your problems with my colleague, who did some stuff around raw sockets on windows, and there is one big problem with - they are usable only for cases, when you need just to send some packet (maybe malformed ), but when you want to establish the full tcp communication, you have a problem, that the ip stack will always intefere your communication - with the RSTs. Problem is, that the IP stack doesn't know nothing about the packet you sent - there is no assigned socket on the client tcp port - so the packet will be delivered to you, but meanwhile the system replies with RST . This is similar to a problem you had with the server port 5678 before.
We looked for some possible solutions -
1st is to find how to switch off this RST feature - it is considered to be security enhancements, when the machine doesn't respond with the RST - so we expect, that there can be some switch in a registry for controlling this behavior.
2nd is little bit more complicated for you, because it involves bit more programming (not too much) and little bit more administration - there are bunch of drivers around on internet, which allows you to somehow directly send and receive ethernet packets. Then you can install them and you will be completelly free to receive and deliver packets in any form . Then you can start even from the lowest level (ARP ) and get the best knowledge of tcp - it will be development of complete ip stack. But this is a little bit time consuming to not be paid . It looks complicated, but there are some shortcuts, which can help you, especially when you are designig that only for edu purposes - like you can ignore packet fragmenting, you can keep only one connection in one time, you can leave the ARP resolving on the normal ip stack on the machine etc.
3rd - learn just by looking what's happening in a network (nearly no programming at all ) ).
Back to your questions
Large value timeouts are twofold thingie - on one side, you have higher probability of succesfull connection establishment, on other side it always consumes resources, because you must keep some structures in memory etc. for this not-yet-opened connection.
Therefore the timeout value should be always ballanced between these two extremes. Timeouts are the most complicated part of any ip stack in my view - they are everywhere
Everything can be done on W2K platform, it is only matter of time . But with tcp consider the fact, that the full blown ip stack exists on a very small devices (embedded stuff), or even on ooold zx-spectrum with 48kb ram in total exists some working ip stack
Well, lot of letters but not too much help for today - you have to decide which way to go now, and then we can continue.
|
|
|
|
|
Thanks, geo_m buddy!
I think the best way to resolve the trouble is to "start even from the lowest level (ARP)". And then I think I can implement a TCP/IP stack myself.
In my mind, the best way to resolvbe the trouble is to ask experienced person the correct way, like you. And then, work hard myself to resolve the trouble
in detail myself.
But I have no experience before. And I think you are experienced in this field. So, can you tell me where can I find useful materials that I can
make a reference? Better free library and online resource, .
regards,
George
|
|
|
|
|
|
Thanks geo_m buddy!
Good luck to you!
regards,
George
|
|
|
|
|
|
I found an example from MSDN on how to use SetHorizontalExtent function to make list box part horizontal scrollable. But it didn't work. Anyone knows how to implement it. Appreciate any response.
itanynj@msn.com
|
|
|
|
|
what's the matter?
I have cracked the difficullty on AutoSizeing the DropDown portion of a ComboBox ,
but failed to display the horizontal scrollbar in the combobox's listbox !!!!!!!!!
I think that's the bug of MS
|
|
|
|
|
I'd like to change some string that user selected by mouse in a web browser.
In other words, user selects some characters at HTML viewer by his left mouse, and activate a popup menu "change" by hist right mouse. At that time I want to change the character's font, color and background color. How can I do it?
I tried it by using CHtmlView class. But, I think there is no method to do it.
Thanks in advance.
|
|
|
|
|
I'd like to make a dialog that has dynamic number of buttons and dynamic number of edit box. Of course I want to control it.
If you know how to do this, please let me know.
|
|
|
|
|
Take a look at www.codeguru.com there's an article regarding on this in the main page of that web site...
hope this helps...
NOTE:
do what you have to do, but why don't you use a editable listctrl and use comboboxes for the selections?
|
|
|
|
|
I used editable listctrl for some areas.
But, I want to add different types of dialog.
If there is five buttons, "1","+","1","=","2". This means 1+1=2.
User changes forth button "=" to "+" by click the button "=".
So I have to add two buttons, "=","4". As a result, it could be 1+1+2=4.
So I will use dynamic dialog.
Thank you.
|
|
|
|
|
I have an (MFC Dialog) application that builds a rather complex url. I want to hit a "Go" button that opens the browser to a URL defined by the application. I have the code built to build the URL string, but I have no idea how to start IE. I'd rather not use DDE, just a command line should be good enough.
Can you point me in the right direction?
|
|
|
|
|