| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | «  : 29-12-2003 12:23 »  |  | 
 
 Добрый день, господа.Необходимо из под WinXP программно формировать, отправлять и получать tcp-пакеты. Пробовал сделать по примеру как это делается в *nix - системах, но, понятно, ничего не вышло. Очень буду признателен, если кто-нибудь подкинет статейку или какой-нибудь сорец..... Очень нужно разобраться....
 И ещё один вопросик: при попытке установить опции на сырой сокет с параметром IP_HDRINCL, борланд си 6-ой сказал, что он вообще не знает, что это такое, хотя в MSDN этот макрос описывается.... В хиадерах включена winsock2.h.... В чём может быть дело?
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ysv_ 
								Помогающий    Offline | 
								|  | « Ответ #1 : 29-12-2003 12:47 »  |  | 
 
 А IP_HDRINCL нету в winsock2.h. Он лежит в Ws2tcpip.h. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #2 : 30-12-2003 00:16 »  |  | 
 
 Для этого тебе нужны  RAW сокеты, например для IP протокола тебе нужно открыть следующий сокет:
 SOCKET sfd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
 
 Вот и структура IP заголовка:
 
 /* The IP header */
 typedef struct iphdr {
 unsigned int h_len:4;          // length of the header
 unsigned int version:4;        // Version of IP
 unsigned char tos;             // Type of service
 unsigned short total_len;      // total length of the packet
 unsigned short ident;          // unique identifier
 unsigned short frag_and_flags; // flags
 unsigned char  ttl;
 unsigned char proto;           // protocol (TCP, UDP etc)
 unsigned short checksum;       // IP checksum
 unsigned int sourceIP;
 unsigned int destIP;
 }IpHeader;
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #3 : 30-12-2003 00:19 »  |  | 
 
 #define IP_HDRINCL      2 /* header is included with data */ |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #4 : 31-12-2003 11:14 »  |  | 
 
 Спасибо за помощь. Получился следующий код:
 #include <vcl.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 
 #pragma hdrstop
 #pragma pack(1)
 
 #define WIN32_LEAN_AND_MEAN
 
 #include "Unit1.h"
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 #pragma resource "*.dfm"
 #define MAX_MESSAGE        4068
 #define MAX_PACKET         4096
 
 #define DEFAULT_MESSAGE    "This is a test"
 
 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;
 
 unsigned  char identity [4];
 unsigned  char data [200];
 } ; /* 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;
 
 
 char           strMessage[MAX_MESSAGE]; // Message to send
 TForm1 *Form1;
 //---------------------------------------------------------------------------
 __fastcall TForm1::TForm1(TComponent* Owner)
 : TForm(Owner)
 {
 }
 //---------------------------------------------------------------------------
 
 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);
 }
 
 void __fastcall TForm1::Button1Click(TObject *Sender)
 {
 WSADATA            wsd;
 SOCKET             s;
 DWORD              i;
 char               *datagram="", ident[] = "ScMX";
 hostent            *h = NULL;
 int                bOpt = 1, y, len;
 char               RecvBuf[200];
 
 struct ipheader *iph = (struct ipheader *) malloc(sizeof(struct ipheader));
 struct tcpheader *tcph = (struct tcpheader *) malloc( sizeof (struct tcpheader));
 struct ps_hdr *ps = (struct ps_hdr *) malloc( sizeof (struct ps_hdr));
 datagram = (char *) malloc(sizeof(struct ipheader) + sizeof(struct tcpheader));
 struct sockaddr_in sin, dest;
 
 
 if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
 {
 ShowMessage("WSAStartup() failed: " + IntToStr(GetLastError()));
 return;
 }
 
 s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0,0);
 if (s == INVALID_SOCKET)
 {
 ShowMessage("WSASocket failed: " + IntToStr(GetLastError()));
 return;
 }
 
 
 iph= (struct ipheader *) datagram;
 tcph=(struct tcpheader *) (datagram+ sizeof(struct ipheader));
 
 sin.sin_family = AF_INET;
 sin.sin_port = htons (110);
 h = gethostbyname("localhost");
 if(h == NULL)
 ShowMessage("╬°шсър gethostbyname");
 
 sin.sin_addr.s_addr = inet_addr (inet_ntoa(*((struct in_addr *)h->h_addr)));
 
 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 = IPPROTO_TCP;
 iph->ip_sum = 0;
 iph->ip_src = inet_addr ("127.0.0.1");
 iph->ip_dst = sin.sin_addr.s_addr;
 
 tcph->th_sport = htons (1999);
 tcph->th_dport = htons (135);
 tcph->th_seq = 666;
 tcph->th_ack = htons (6234);
 tcph->th_x2 = 0;
 tcph->th_off = 5;
 tcph->th_flags = 16; // SYN
 tcph->th_win = htons(65535);
 tcph->th_sum = 0;
 tcph->th_urp = 0;
 
 strncpy((char *)tcph->identity,ident,4);
 
 for(i = 0; i < strlen(strMessage); i++)
 tcph->data=strMessage;
 
 ps->source_address   = inet_addr ("127.0.0.1");
 ps->dest_address  = sin.sin_addr.s_addr;
 ps->placeholder  = 0;
 ps->protocol  = IPPROTO_TCP;
 ps->tcp_length  = htons(sizeof(struct tcpheader));
 
 ps->tcp = *tcph;
 
 tcph->th_sum = checksum((unsigned short *)ps, sizeof(struct ps_hdr));
 iph->ip_sum  = checksum((unsigned short *)iph, sizeof(struct ipheader));
 
 setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
 
 if (sendto(s, datagram, iph->ip_len, 0, (SOCKADDR *)&sin, sizeof(sin)) == SOCKET_ERROR)
 {
 ShowMessage("sendto() failed: " + IntToStr(WSAGetLastError()));
 return;
 }
 
 memset(datagram,0,strlen(datagram));
 
 i = 0;
 len = sizeof(sin);
 
 i = recvfrom(s, RecvBuf, 200, 0,(sockaddr*)&sin, &len);
 if(i > 0)
 RichEdit1->Lines->Add("╧юыєўхэ яръхЄ.");
 /*while(i < 1)
 {
 memset(RecvBuf, 0, sizeof(RecvBuf));
 i = recv(s, RecvBuf, 200, 0);
 }
 RichEdit1->Lines->Add("╧юыєўхэ яръхЄ.");  */
 
 closesocket(s) ;
 WSACleanup() ;
 }
 //---------------------------------------------------------------------------
 
 Никак не могу понять почему в ответ не приходит вообще никакого пакета (recivefrom), когда, по идее, должен прийти пакет с флагом ask.
 Очень буду признателе за помощь.
 Цель: получить tcp - пакет от удалённой машины, дабы в дальнейшем из tcp-заголовка достать размер окна....
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #5 : 31-12-2003 13:36 »  |  | 
 
 Попробуй послать на сокет открытый тобой, чтоб увидеть если ваще пакет приходит. И почему тебе просто не вызвать getsockopt с опцией 
 SO_MAX_MSG_SIZE
 Maximum size of a message for message-oriented socket types (for example, SOCK_DGRAM). Has no meaning for stream oriented sockets.
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #6 : 02-01-2004 10:52 »  |  | 
 
 Попробую послать что либо на этот сокет. Пробовал повесить сервер на сыром сокете на 1999 порту, но он ничего не получает. Если не сложно поясните смысл использовать в данном случае getsockopt. Может есть ещё какой-то варионт осуществить данную цель?
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #7 : 02-01-2004 14:45 »  |  | 
 
 Вешай сервак на нормальном сокете, а от на стороне клиента играйся с сырыми, иначе самому над будет отсылать АЦК. Не понял что ты именно хош узнаить про getsockopt.
 
 Во нашел пример и выкладываю насколько понял он рабочий:
 
 --------head.h-----------------------------------------------
 #include <winsock2.h>
 #include <windows.h>
 #include <ws2tcpip.h>
 #include <stdio.h>
 
 
 unsigned short checksum(unsigned short *addr, int len);
 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) */
 
 // Psuedo Header
 
 
 struct body
 {
 
 unsigned char data [40];
 
 
 };
 
 
 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
 
 struct tcpheader tcp;
 struct body data;
 
 };
 -------------------EOF-----------------------------------------
 
 
 ---------------main.cpp-----------------------------------
 #include "head.h"
 
 #define PORT 25
 
 int main (void)
 {
 
 WSADATA wsd;
 char *datagram="";
 int bOpt = 1;
 char info[30] ="das ist ein test";
 
 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 *) malloc(sizeof(struct
 ipheader));
 struct tcpheader *tcph = (struct tcpheader *) malloc( sizeof
 (struct tcpheader));
 struct body *bo = (struct body *) malloc( sizeof (struct body));
 struct ps_hdr *ps = (struct ps_hdr *) malloc( sizeof (struct
 ps_hdr));
 
 datagram = (char *) malloc(sizeof(struct ipheader) + sizeof(struct
 tcpheader)+sizeof (struct body));
 
 
 
 struct sockaddr_in sin;
 
 
 
 iph= (struct ipheader *) datagram;
 tcph=(struct tcpheader *) (datagram+ sizeof(struct ipheader));
 bo= (struct body *) (datagram+sizeof(struct ipheader)+ sizeof(struct
 tcpheader));
 memset(bo->data,'\0',strlen((char *)bo->data));
 
 
 sin.sin_family = AF_INET;
 sin.sin_port = htons (PORT);
 sin.sin_addr.s_addr = inet_addr ("193.99.144.71");
 
 
 printf("%i\n",sizeof(datagram));
 iph->ip_hl = 5;
 iph->ip_v = 4;
 iph->ip_tos = 0;
 iph->ip_len = sizeof (struct ipheader) + sizeof (struct
 tcpheader)+sizeof(struct body);
 
 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 ("192.168.0.113");
 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 = htons (6234);
 tcph->th_x2 = 0;
 tcph->th_off = 5;
 tcph->th_flags = 16; // SYN
 tcph->th_win = htons(65535);
 tcph->th_sum = 0;
 tcph->th_urp = 0;
 
 
 
 
 
 // Build the Psuedo Header
 
 ps->source_address = inet_addr ("192.168.0.113");
 ps->dest_address = sin.sin_addr.s_addr;
 ps->placeholder = 0;
 ps->protocol = IPPROTO_TCP;
 ps->tcp_length = htons(sizeof(struct tcpheader)+sizeof(struct
 body));
 
 ps->tcp = *tcph;
 ps->data=*bo;
 
 strcpy((char *)bo->data,info);
 // Calculate Checksum
 
 
 tcph->th_sum = checksum((unsigned short *)ps, sizeof(struct
 ps_hdr));
 iph->ip_sum = checksum((unsigned short *)iph, sizeof(struct
 ipheader));
 
 
 
 
 // ENABLE IPHDRINCL
 
 if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt,
 sizeof(bOpt)) == SOCKET_ERROR)
 {
 printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
 return -1;
 }
 
 
 
 // Send The Packet
 
 if (sendto(s, datagram, iph->ip_len, 0, (SOCKADDR *)&sin,
 sizeof(sin)) == SOCKET_ERROR)
 {
 printf("sendto() failed: %d\n", WSAGetLastError());
 return -1;
 }
 
 
 return 0;
 }
 -------------------EOF--------------------------------
 
 
 
 
 ----------------------check.cpp----------------------------
 #include "head.h"
 
 unsigned short checksum(unsigned short *addr, int len)
 {
 register int sum = 0;
 u_short answer = 0;
 register u_short *w = addr;
 register int nleft = len;
 
 /*
 * 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.
 */
 while (nleft > 1)
 {
 sum += *w++;
 nleft -= 2;
 }
 
 /* mop up an odd byte, if necessary */
 if (nleft == 1)
 {
 *(u_char *) (&answer) = *(u_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);
 }
 ------------------------------EOF-------------------------------------
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #8 : 05-01-2004 14:05 »  |  | 
 
 Спасибо за помощь - кажется почти разобрался и уже почти работает   , за малым исключением того, что вместо пакетов с конкретного ip я получаю все пакеты (приходиться фильтровать в программе). Сделал прослушку сокета при помощи WSAIoctl. При помощи каких параметров WSAIoctl можно заставить сокет принимать пакеты только с нужного ip? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #9 : 05-01-2004 14:27 »  |  | 
 
 Ты хочеш сказать что шлёшь на оперделенный IP а получаешь от нескольких, чтото не вяжется, покажи сырец, по идее если шлешь на определенный IP и определенный сокет, то должен отозватся только адрессуемый, или я чтото недопонимаю? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #10 : 05-01-2004 14:54 »  |  | 
 
 Точно - ты что-то не допонимаешь   ). Я один сокет повесил на интерфейс, т.е. он работает как снифер (ловит все пакеты вообще независимо от того отправляю я что-то или нет). Если я отправляю пакет с син флагом, то среди всей кучи принятых пакетов (сетевая активность всегда хоть какая-то есть в сети) есть пакет с аск флагом от той машины, которой был послан с син флагом. Вопрос в том, как сделать так, чтобы сокет работал не просто в режиме снифера, а принимал только те пакеты, которые нужны без дополнительных алгоритмов фильтрации... |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| ixania 
								Гость
 | 
								|  | « Ответ #11 : 05-01-2004 15:27 »  |  | 
 
 Дума придется всетаки написать фильтр    , либо открой другой нормальный сокет, вот тебе и фильтр. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #12 : 10-01-2004 08:51 »  |  | 
 
 Печально, но видимо прийдётся делать фильтр: не хотел чтобы при большой сетевой активности программа сильно грузила ось....Спасибо за помощь.
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Chkalov 
								Гость
 | 
								|  | « Ответ #13 : 26-01-2004 09:50 »  |  | 
 
 А как ты сокет повесил на интерфейс???раскажи пожалуйста поподробней
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Avatar 
								Гость
 | 
								|  | « Ответ #14 : 26-01-2004 10:29 »  |  | 
 
 Сырой сокет и повесил (сервером). |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Chkalov 
								Гость
 | 
								|  | « Ответ #15 :  27-01-2004 08:06 »   |  | 
 
 Так ты  создал  сырой сокет повесил его сервером и он стал ловить все пакеты приходящие на машину?? или как? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	|  |