Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: icmp-пакуты на MFC  (Прочитано 17791 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Junk
Гость
« : 10-07-2006 11:17 » new

Подскажите, пожалуста как в MFC создать и заставить работать сокет, получающий и отпправляющий ICMP-паеты?
Для CSocket::Create можно установить тока
nSocketType
SOCK_STREAM or SOCK_DGRAM.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 10-07-2006 12:20 » 

Я не думаю, что есть средства в MFC, делать ICMP сокеты. По крайней мере, в чистом WINAPI нужно заголовки править вручную. Сейчас я как раз с этим разбираюсь. Если что, скину готовый код Улыбаюсь
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Junk
Гость
« Ответ #2 : 10-07-2006 13:11 » 

Что за код? Какую программу пишешь?
Кидай - если там не сложно разбираться
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 10-07-2006 14:05 » 

Я пока свободно эксперементирую Улыбаюсь Код будет под Линукс. Но переправить под винду, я думаю будет не сложно.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Junk
Гость
« Ответ #4 : 10-07-2006 14:21 » 

Спасибо. Попробую разобраться. Мой e-mail должен быть в инфе слева
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 10-07-2006 19:59 » 

Вот обешанная программа. Она пингует адрес 127.0.0.1 . Вроде написал комментарии, если что то будет не понятно, спрашивай.

Код:
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <resolv.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>

//Определение структуры Ping заголовка
#define PACKETSIZE 64 /* байта '*/
struct pck
{
     u_int8_t type; /* message type */
     u_int8_t code; /* type sub-code */
     u_int16_t checksum;
     u_int16_t id;
     u_int16_t sequence;
     char msg [32];
};


unsigned short checksum(void *b, int len)        //Функция проверки контрольной суммы
{
unsigned short *buf = (unsigned short *)b, result;
    unsigned int sum=0;
    for ( sum = 0 ; len > 1 ; len-=2)
{
sum += *buf;    /* Складываем все двухбайтовое блова */
buf++;

}

    if ( len == 1 )                     /* если остался лишний байт, */
        sum += *(unsigned char*) buf; /* прибавляем его к сумме */
    sum = (sum >> 16) + (sum & 0xffff); /* добавляем перенос */
    sum += (sum >> 16);                                        /* еще раз */
    result = ~sum;                          /* инвертируем результат */
    return result;            /*    возвращаем двухбайтовое значейие */
}


int ID;                     // Индефикатор пакетов
int sdin, sdout;                                       // Индефикатор сокета
bool quit=false;
int step=0;

#define MAXINBUF 255

bool show(unsigned char *buff, int len)   // Функция проверяет и показывает сообшение
{
bool res=false; 
ip *mip= (ip *) buff;
if (len >= (sizeof(pck)+mip->ip_hl * 4))
{
pck *pckt= (pck *) &buff[mip->ip_hl * 4];
if ((pckt->id ==ID) && (pckt->type == ICMP_ECHOREPLY)) res=true;
}
return res;

}


void* icmpin(void *arg)                          //Поток приема
{
#define MAXINBUF 255
unsigned char buff[MAXINBUF];                      //Буфер приема
pck *pckt= (pck *) buff;
    int i;
int rec;                                           //Число принятых байт
struct sockaddr_in dest;
socklen_t len;
while (!quit)
{
len=sizeof(dest);
bzero(buff,MAXINBUF);               // Чистим буфер
rec = recvfrom(sdin, buff, sizeof(buff), 0, (sockaddr *)&dest, &len);
if (rec>0)
{
if (show(buff,rec))
{
printf("Receive Message from %s \n", inet_ntoa(dest.sin_addr));
step++;
}
}
}
return NULL;
}

int main()
{
struct protoent* proto;                       // Индефикатор протокола
proto = getprotobyname("ICMP");               // Запрашиваем номер протокола
sdin  = socket(PF_INET, SOCK_RAW, proto->p_proto);   //Открываем сокет
sdout = socket(PF_INET, SOCK_RAW, proto->p_proto);   
ID= getpid();                                     // Запрашиваем ID процесса
//настройка сокета
int param=1;
bool quit=false;
// Разрешение на ручное создание заголовков
//if (setsockopt(sdout, SOL_IP, IP_HDRINCL, &param, sizeof(param)) != 0) quit=true;
// Увеличиваем TTL до 255
param=255;
    if (!quit && (setsockopt(sdout, SOL_IP, IP_TTL, &param, sizeof(param)) != 0)) quit=true;
// Переводим сокет в неблокируемый режим
param=1;
    if (!quit && (ioctl(sdin,  FIONBIO, &param) != 0)) quit=true;
if (!quit)
{
pthread_t pt;
//создаем поток на прием
if (pthread_create(&pt, 0, icmpin, 0) >= 0)
{
int cnt=1;                                       //Счетчик посылок
int i;
struct pck pckt;
struct sockaddr_in dest;                         //Адрес абонента
bzero(&dest, sizeof(dest));                      /* обнуляем структуру */
        dest.sin_family = AF_INET;                       /* выбираем протокол */
        dest.sin_addr.s_addr = inet_addr("127.0.0.1");   /* IP адресс */

socklen_t len;

while(step <4)
{
len=sizeof(dest);                           
/*— Инициализируем отправляемый пакет— */
bzero(&pckt, sizeof(pckt));             /* обнуляем содержимое  */
pckt.type = ICMP_ECHO;              /*запрашиваем эхо сервис  */
pckt.id = ID;               /* задаем идентификатор  */
/*заполняем буфер */
for (i = 0; i < 31; i++ ) pckt.msg[i] = (char)i+'0';
                pckt.msg[i] = 0;                         /* завершаем строку нулевым символом   */
                pckt.sequence = cnt++;       /* устанавливаем счетчик     */
/* вычисляем контрольную сумму    */
pckt.checksum = checksum(&pckt, sizeof(pckt));         
      /* отправляем!    */
if (sendto(sdout, &pckt, sizeof(pckt), 0, (sockaddr *)&dest, sizeof(dest))<= 0 )
                quit=true;
sleep(1);                   /* пауза в течение одной секунды    */

}
quit=true;
sleep(1);
close(pt);
}
else quit=true;
}



close(sdin);
close(sdout);
return 0;
}

Некоторые отрывки текста мной выдраны из книги Ш.Уолтон - Создание сетевых приложений в среде Linux
« Последнее редактирование: 16-12-2007 16:33 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Junk
Гость
« Ответ #6 : 21-08-2006 09:14 » 

Создал функцию инициализации сокета для посылки ICMP
----------------------------------------------------------
int SocketInit (void)
{
   int res=0;
   struct protoent* proto;                        
   proto = getprotobyname("ICMP");
   icmpin  = socket(PF_INET, SOCK_RAW, proto->p_proto);
   icmpout = socket(PF_INET, SOCK_RAW, proto->p_proto);


   HANDLE   ptThreadIn;
   iRead = iWrite = 0;
      
   ptThreadIn = CreateThread( NULL, 0,(LPTHREAD_START_ROUTINE) ICMPin,0, 0, 0);

   IpOptionHeader      ipopt;
   ZeroMemory(&ipopt, sizeof(ipopt));
   ipopt.code = IP_RECORD_ROUTE;
   ipopt.ptr  = 4; 
   ipopt.len  = 39;
 
   if ( setsockopt(icmpout, IPPROTO_IP, IP_OPTIONS, (char *)&ipopt, sizeof(ipopt)) == SOCKET_ERROR)
      res = 1;

   return res;
}
----------------------------------------------------------
функция посылки ICMP-сообщений
----------------------------------------------------------
int SendIcmpPacket (char * Address, USHORT seq)
{
   int   datasize = DEF_PACKET_SIZE;
   char   *icmp_data = NULL;
   SOCKADDR_IN   dest;   

   datasize += sizeof(IcmpHeader);
   icmp_data = (char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);
   memset(icmp_data,0,MAX_PACKET);

   IcmpHeader *icmp_hdr = NULL;
             char       *datapart = NULL;
             icmp_hdr = (IcmpHeader*)icmp_data;
             icmp_hdr->i_type = ICMP_ECHO;
             icmp_hdr->i_code = 0;
             icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
             icmp_hdr->i_cksum = checksum((USHORT*)icmp_data, datasize);
             icmp_hdr->i_seq = seq;
   icmp_hdr->timestamp = GetTickCount();
             datapart = icmp_data + sizeof(IcmpHeader);
             memset(datapart,'X', datasize - sizeof(IcmpHeader));

   dest.sin_family = AF_INET;
   dest.sin_addr.s_addr = inet_addr(Address);

   if ( sendto(icmpout, icmp_data, datasize, 0, (struct sockaddr*)&dest, sizeof(dest)) == SOCKET_ERROR)
      return WSAGetLastError();
   else
      return 0;
}
----------------------------------------------------------

Вот тока проверяю я всю эту посылку с помощью сниффера Ethereal - показывает, что ничего не отсылается. И как ловить ответы?
« Последнее редактирование: 16-12-2007 16:34 от Алексей1153++ » Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 21-08-2006 18:37 » 

Код:
icmp_data = (char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PACKET);
А чем тебе не нравится функция new?

Код:
 icmp_hdr->i_cksum = checksum((USHORT*)icmp_data, datasize);
             icmp_hdr->i_seq = seq;
   icmp_hdr->timestamp = GetTickCount();
             datapart = icmp_data + sizeof(IcmpHeader);
             memset(datapart,'X', datasize - sizeof(IcmpHeader));
Вообше то контрольная сумма всегда расчитывается после заполнения всех остальных полей пакета. Иначе контрольная сумма будет неверна. И пакет будет отвергнут.

« Последнее редактирование: 16-12-2007 16:35 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Junk
Гость
« Ответ #8 : 22-08-2006 14:43 » 

А чем тебе не нравится функция new?

Нравится, тока я этот отрывок брал из примера, разве почти не одно и то же?

Про контрольную сумму - спасибо - все возвращается
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 22-08-2006 15:17 » 

Оно то делает одно и тоже, только new  намного меньше нужно писать. Твоя бы строчка выгледила бы так:
Код:
icmp_data = new char[MAX_PACKET];
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
sss
Специалист

ru
Offline Offline

« Ответ #10 : 23-08-2006 04:24 » 

Я пользуюсь по старинке, динамической загрузкой системной DLL. Любые попытки создать через wsock у меня провалились Жаль.

Код:

typedef class CIcmpLibrary
{
public:
  CIcmpLibrary();
  ~CIcmpLibrary();
public:
  HANDLE (WINAPI *pIcmpCreateFile)(VOID);
  BOOL  (WINAPI *pIcmpCloseHandle)(HANDLE);
  DWORD (WINAPI *pIcmpSendEcho)
          ( HANDLE IcmpHandle,  IPAddr DestinationAddress ,
            LPVOID RequestData, WORD RequestSize,
            PIP_OPTION_INFORMATION RequestOptions,
            LPVOID ReplyBuffer, DWORD ReplySize,
            DWORD Timeout);
  DWORD (WINAPI *pIcmpSendEcho2)
           ( HANDLE IcmpHandle,  HANDLE Event,
            FARPROC ApcRoutine, PVOID ApcContext,
            IPAddr DestinationAddress,
            LPVOID RequestData, WORD RequestSize,
            PIP_OPTION_INFORMATION RequestOptions,
            LPVOID ReplyBuffer, DWORD ReplySize,
            DWORD Timeout);

  HANDLE hIcmpDll;
  BOOL bValid;
public:
  BOOL getValid() { return bValid;};
public:
  __declspec( property ( get = getValid))
  BOOL                      Valid;
} *PIcmpLibrary;


CIcmpLibrary::CIcmpLibrary()
{
  bValid = FALSE;

  // Динамически загрузим ICMP.DLL
  hIcmpDll = LoadLibrary(TEXT("ICMP.DLL"));
  if (hIcmpDll == NULL)
  {
    return;
  }

  // IcmpCreateFile
  pIcmpCreateFile  = (HANDLE (WINAPI *)(void))
  GetProcAddress((HMODULE)hIcmpDll, "IcmpCreateFile");

  // IcmpCloseFile
  pIcmpCloseHandle = (BOOL (WINAPI *)(HANDLE))
         GetProcAddress((HMODULE)hIcmpDll, "IcmpCloseHandle");

  // IcmpSendEcho
  pIcmpSendEcho = (DWORD (WINAPI *)
                  (HANDLE, IPAddr, LPVOID, WORD,
                   PIP_OPTION_INFORMATION,
                   LPVOID, DWORD, DWORD))
                   GetProcAddress((HMODULE)hIcmpDll,
                   "IcmpSendEcho");

  pIcmpSendEcho2 =  ( DWORD (WINAPI *)
                    ( HANDLE, HANDLE, FARPROC,
                      PVOID, IPAddr, LPVOID, WORD,
      PIP_OPTION_INFORMATION,
      LPVOID, DWORD, DWORD))
                      GetProcAddress((HMODULE) hIcmpDll,
                      "IcmpSendEcho2");

  // Проверим
  if ( pIcmpCreateFile == NULL   ||
       pIcmpCloseHandle == NULL  ||
       pIcmpSendEcho == NULL     ||
       pIcmpSendEcho2 == NULL)
  {
    FreeLibrary((HMODULE) hIcmpDll);
    return;
  }
  bValid = TRUE;
}

CIcmpLibrary::~CIcmpLibrary()
{
  FreeLibrary((HMODULE) hIcmpDll);
}

// Пример использования...

  HANDLE        hIcmpFile;
  hIcmpFile = IcmpLibrary.pIcmpCreateFile();
  if ( hIcmpFile)
  {
     IP_OPTION_INFORMATION ipInfo   = {0};
     ICMP_ECHO_REPLY       icmpEcho = {0};
     ipInfo.Ttl = 255;
     ipInfo.Tos = 0;
     ipInfo.Flags = 0;
     ipInfo.OptionsData = 0;
     ipInfo.OptionsSize = 0;

     //Функция выполняется синхронно
     IcmpLibrary.pIcmpSendEcho( hIcmpFile, ItemData->ipDest,
                                               0, 0, &ipInfo, &icmpEcho,
                                               sizeof(ICMP_ECHO_REPLY),
                                               iTimeout);
     if ( ! icmpEcho.Status)
     {
        //OK
     }
     else
     {
        //FAIL
     }

    IcmpLibrary.pIcmpCloseHandle( hIcmpFile);
  } // hIcmpFile
Записан

while (8==8)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines