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 » |
|
Так ты создал сырой сокет повесил его сервером и он стал ловить все пакеты приходящие на машину?? или как?
|
|
|
Записан
|
|
|
|
|