Разобрать ip пакет
От: prometey Россия  
Дата: 17.02.04 20:02
Оценка:
Всем привет!

Надеюсь кто-нибудь поможет решить следующую проблему: мне необходимо
написать udp сервер, который может разбирать Ip, udp заголовки.
Я уже прочитал много литературы, исследовал утилиту ping из MSDN, но
к сожалению, пока не добился положительного результата.
Windows никак не хочет давать мне заголовок! Получаю только передаваемые
данные. Ниже привожу исходный текст, скорее всего там ошибка.
Буду признателен любой помощи, особенно за работающий кусок кода!

#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "winsock2.h"
#include "windows.h"
#include "stdlib.h"
#define IP_HDRINCL 2

// Udp header
typedef struct udphdr {
unsigned short src_portno;
unsigned short dst_portno;
unsigned short udp_length;
unsigned short udp_checksum;
}UdpHeader;
// IP header
typedef struct iphdr {
unsigned int h_len; // length of the header
unsigned int version; // 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;

char src[10];
char dest[10];
char ds[15];
#define MAX_PACKET 1024
#define PORT 666 // порт сервера
char Buffer[1024];

int main(int argc, char* argv[])
{
WSADATA wsadata;
printf("UDP Server\n");
// шаг 1 — подключение библиотеки
//&wsadata
if (WSAStartup(0x202,&wsadata))
{
printf("WSAStartup error: %d\n",
WSAGetLastError());
return -1;
}

SOCKET my_sock;

// создание сокета
my_sock= socket(AF_INET,SOCK_RAW,IPPROTO_UDP);

if (my_sock==INVALID_SOCKET)
{
printf("Socket() error: %d\n",WSAGetLastError());
WSACleanup();
return -1;
}

// шаг 3 — связывание сокета с локальным адресом
sockaddr_in local_addr;
local_addr.sin_family=AF_INET;
local_addr.sin_addr.s_addr=INADDR_ANY;
local_addr.sin_port=htons(PORT);

if (bind(my_sock,(sockaddr *) &local_addr,
sizeof(local_addr)))
{ printf("bind error: %d\n",WSAGetLastError());
closesocket(my_sock);
WSACleanup();
return -1;
}


// Обработка
while(1)
{
sockaddr_in client_addr;
int client_addr_size = sizeof(client_addr);
int bsize=recvfrom(my_sock,Buffer,
MAX_PACKET,0,
(sockaddr *) &client_addr, &client_addr_size);
if (bsize==SOCKET_ERROR)
printf("recvfrom() error: %d\n",
WSAGetLastError());

// попытка прочитать Ip заголовок
IpHeader *iphdr = (IpHeader *)Buffer;


IN_ADDR sa1;
printf("From ");
sa1.s_addr = iphdr->destIP; // пытаюсь определить destination adress
printf(inet_ntoa(sa1));
// попытка определить тип протокола
if(iphdr->proto == IPPROTO_TCP) printf("TCP ");
if(iphdr->proto == IPPROTO_UDP) printf("UDP ");


// Определяем IP-адрес клиента и прочие атрибуты(но уже другим способом)
HOSTENT *hst;
hst=gethostbyaddr((char *)
&client_addr.sin_addr,4,AF_INET);
printf("+%s [%s:%d] new DATAGRAM!\n",
(hst)?hst->h_name:"Unknown host",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
printf("From ");
// добавление завершающего нуля
Buffer[bsize]=0;

// Вывод на экран
printf("C=>S:%s\n",Buffer);

// посылка датаграммы клиенту
sendto(my_sock,&Buffer[0],bsize,0,
(sockaddr *)&client_addr, sizeof(client_addr));
}
return 0;
}




С уважением, Алексей.

18.02.04 13:18: Перенесено из 'Работа'
Re: Разобрать ip пакет
От: _Shishkov Украина  
Дата: 18.02.04 10:27
Оценка:
Не вдавался в подробности, но не увидел вызова
BOOL flag = TRUE;
setsockopt(my_sock, IP_PROTOIP, IP_HDRINCL, (char *)&flag, sizeof(flag));
Эта опция разрешает возвращать данные с заголовком. Сделай вызов перед тем как
вызвать bind() или recv() — должна помочь.
Алексей
Re: Разобрать ip пакет
От: Michael Chelnokov Украина  
Дата: 18.02.04 10:31
Оценка:
Здравствуйте, prometey, Вы писали:

P>Windows никак не хочет давать мне заголовок! Получаю только передаваемые

P>данные. Ниже привожу исходный текст, скорее всего там ошибка.

P> my_sock= socket(AF_INET,SOCK_RAW,IPPROTO_UDP);


IPPROTO_IP?
Re: Разобрать ip пакет
От: butcher Россия http://bu7cher.blogspot.com
Дата: 18.02.04 10:34
Оценка:
Здравствуйте, prometey.

Вы писали 17 февраля 2004 г., 23:02:35:

p> #define IP_HDRINCL 2


интересно получается, а для чего тогда объявлена эта константа?
setsockopt не забываем..

--
С уважением, butcher
Posted via RSDN NNTP Server 1.8 beta

Нет ничего невозможного..
Re[2]: Разобрать ip пакет
От: prometey Россия  
Дата: 18.02.04 19:51
Оценка:
Здравствуйте


Спасибо всем кто откликнулся! Вообще-то я уже устанавливал
setsockopt(my_sock, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag));

Только это не помогало. Проверил снова и опять безуспешно....
Дело в чём-то другом...

Алексей.
Re[3]: Разобрать ip пакет
От: butcher Россия http://bu7cher.blogspot.com
Дата: 19.02.04 09:00
Оценка:
Здравствуйте, prometey.

Вы писали 18 февраля 2004 г., 22:51:35:

p> Спасибо всем кто откликнулся! Вообще-то я уже устанавливал

p> setsockopt(my_sock, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag));

хм.. действительно, видимо это действует только на посылку..
тогда только остаётся WSAIoctl ( .. SIO_RCVALL .. ) и выбирать
нужные тебе пакеты..
Если найдёшь способ без SIO_RCVALL, запости сюда, я тоже ещё поищу..

--
С уважением, butcher
Posted via RSDN NNTP Server 1.8 beta

Нет ничего невозможного..
Re: Разобрать ip пакет
От: eax  
Дата: 20.02.04 11:07
Оценка:
вот работающий код

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ws2_32.lib")
#include <conio.h>
#include <stdio.h>
#include <winsock2.h>
#define SIO_RCVALL  0x98000001
#define MAX_IP_SIZE 2048
typedef struct  _IP_RHDR {
        UCHAR   VerLen;
        UCHAR   Service;
        UCHAR   Length[2];
        UCHAR   Ident[2];
        UCHAR   Flagoff[2];
        UCHAR   Timelive;
        UCHAR   Protocol;
        UCHAR   Checksum[2];
        UCHAR   Source[4];
        UCHAR   Destination[4];
        UCHAR   Data[1];
} IP_RHDR, *PIP_RHDR;
typedef struct  _TCP_RHDR {
        UCHAR   Source[2];
        UCHAR   Destination[2];
        UCHAR   Seq[4];
        UCHAR   Ack[4];
        UCHAR   Rsvd0:4;
        UCHAR   Offset:4;
        UCHAR   Flags:6;
        UCHAR   Rsvd1:2;
        UCHAR   Window[2];
        UCHAR   Checksum[2];
        UCHAR   UrgPoint[2];
        UCHAR   Data[1];
} TCP_RHDR, *PTCP_RHDR;
#define PROTO_ICMP      (0x01)
#define PROTO_TCP       (0x06)
#define PROTO_UDP       (0x11)
HANDLE         hThread;
SOCKET         sockRaw = 0;
volatile BOOL  terminated = FALSE;
void writeFile(PSTR filename, PSTR pBuffer, int size)
{
  HANDLE  hFile;
  DWORD   num;
  hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
                     FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                     OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  SetFilePointer(hFile, 0, 0, FILE_END);
  WriteFile(hFile, pBuffer, size, &num, NULL);
  CloseHandle(hFile);
}
void parsepacket(WSABUF *wsabuf)
{
  PIP_RHDR  pIPHdr;
  BYTE      protoIP;
  char      buffer[255];
  pIPHdr = (PIP_RHDR)wsabuf->buf;
  protoIP = pIPHdr->Protocol;
  wsprintf(buffer, "Source: %02d.%02d.%02d.%02d, Dest: %02d.%02d.%02d.%02d,Length: %d, Protocol: ",
           pIPHdr->Source[0], pIPHdr->Source[1],
           pIPHdr->Source[2], pIPHdr->Source[3],
           pIPHdr->Destination[0], pIPHdr->Destination[1],
           pIPHdr->Destination[2], pIPHdr->Destination[3],
           MAKEWORD(pIPHdr->Length[1], pIPHdr->Length[0]));
  writeFile("log.log", buffer, strlen(buffer));
  if(protoIP == PROTO_ICMP)
    writeFile("log.log", "ICMP\n", strlen("ICMP\n"));
  if(protoIP == PROTO_TCP)
    writeFile("log.log", "TCP\n", strlen("TCP\n"));
  if(protoIP == PROTO_UDP)
    writeFile("log.log", "UDP\n", strlen("UDP\n"));
  writeFile("log.log", wsabuf->buf, wsabuf->len);
  writeFile("log.log", "\n\n\n", strlen("\n\n\n"));
}
void sniff(void)
{
  WSABUF  wsabuf;
  DWORD   bytes = 0, flags = 0;
  char    buffer[MAX_IP_SIZE];
  int     packetcount = 0;
  wsabuf.buf = buffer;
  while(!terminated) {
    wsabuf.len = MAX_IP_SIZE;
    memset(buffer, 0, MAX_IP_SIZE);
    if(SOCKET_ERROR == WSARecv(sockRaw, &wsabuf, 1, &bytes, &flags, NULL,
NULL))
      printf("WSARecv failed. Code %d", WSAGetLastError());
    wsabuf.len = bytes;
    parsepacket(&wsabuf);
    printf("\rcount=%d", packetcount++);
  }
}
BOOL GetAdapter(SOCKET s, SOCKADDR_IN *iface, int num)
{
  SOCKET_ADDRESS_LIST  *slist = NULL;
  char                 buf[2048];
  DWORD                bytes;
  if(SOCKET_ERROR == WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, 2048,
&bytes, NULL, NULL))
    return TRUE;
  slist = (SOCKET_ADDRESS_LIST *)buf;
  if(num >= slist->iAddressCount) return TRUE;
  iface->sin_addr.s_addr = ((SOCKADDR_IN
*)slist->Address[num].lpSockaddr)->sin_addr.s_addr;
  return FALSE;
}
BOOL Startup(void)
{
  WSADATA      WSAData;
  SOCKADDR_IN  iface;
  DWORD        bytes, tid;
  if( WSAStartup(MAKEWORD(2, 2), &WSAData) )
  {
    printf("WSAStartup failed");
    return TRUE;
  }
  sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, 0);
  if(sockRaw == INVALID_SOCKET) {
    printf("WSASocket failed");
    return TRUE;
  }
  memset(&iface, 0, sizeof(iface));
  iface.sin_family = AF_INET;
  if( GetAdapter(sockRaw, &iface, 0) )
    return TRUE;
  if( bind(sockRaw, (SOCKADDR *)&iface, sizeof(iface)) == SOCKET_ERROR )
  {
    printf("Bind failed");
    return TRUE;
  }
  int optval = 1;
  if( WSAIoctl(sockRaw, SIO_RCVALL, &optval, sizeof(optval), NULL, 0,
&bytes, NULL, NULL) == SOCKET_ERROR )
  {
    printf("WSAIoCtl failed");
    return TRUE;
  }
  optval = 1000000;
  setsockopt(sockRaw, SOL_SOCKET, SO_RCVBUF, (char *)&optval, sizeof(int));
  hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)sniff, 0, 0,
&tid);
  return FALSE;
}
void Shutdown(void)
{
  if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
  WSACleanup();
}
void main(void)
{
  if( Startup() )
    return;
  getch();
  terminated = TRUE;
  WaitForSingleObject(hThread, INFINITE);
  CloseHandle(hThread);
  Shutdown();
}
Re: Разобрать ip пакет
От: BArt  
Дата: 20.02.04 12:53
Оценка:
Здравствуйте, prometey, Вы писали:

P>Всем привет!


P>Надеюсь кто-нибудь поможет решить следующую проблему: мне необходимо

P>написать udp сервер, который может разбирать Ip, udp заголовки.
P>Я уже прочитал много литературы, исследовал утилиту ping из MSDN, но
P>к сожалению, пока не добился положительного результата.

Мое мнение — человеку не хватает WinPcap.
Re[2]: Разобрать ip пакет
От: Аноним  
Дата: 21.02.04 17:48
Оценка:
Здравствуйте!

Большое спасибо eax за код!!!! Только появилась новая проблема: я отсылаю Ip пакет(протокол udp), но Ваша программа считает, что передается icmp пакет и показывает какую-то ерунду. Я также скомпилил программу из статьи на rsdn "сниффер — шит и меч" и она
показывает тоже самое, но ведь абсолютно точно передается udp пакет!!!! Я протестировал это на
windows 2000 professional и windows xp professional и везде одно и тоже! Мне очень интересно в чём же проблема?

С уважением, Алексей.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.