Junk
Гость
|
|
« : 10-07-2006 11:17 » |
|
Подскажите, пожалуста как в MFC создать и заставить работать сокет, получающий и отпправляющий ICMP-паеты? Для CSocket::Create можно установить тока nSocketType SOCK_STREAM or SOCK_DGRAM.
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #1 : 10-07-2006 12:20 » |
|
Я не думаю, что есть средства в MFC, делать ICMP сокеты. По крайней мере, в чистом WINAPI нужно заголовки править вручную. Сейчас я как раз с этим разбираюсь. Если что, скину готовый код
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Junk
Гость
|
|
« Ответ #2 : 10-07-2006 13:11 » |
|
Что за код? Какую программу пишешь? Кидай - если там не сложно разбираться
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #3 : 10-07-2006 14:05 » |
|
Я пока свободно эксперементирую Код будет под Линукс. Но переправить под винду, я думаю будет не сложно.
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
Junk
Гость
|
|
« Ответ #4 : 10-07-2006 14:21 » |
|
Спасибо. Попробую разобраться. Мой e-mail должен быть в инфе слева
|
|
|
Записан
|
|
|
|
Finch
Спокойный
Администратор
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, ¶m, sizeof(param)) != 0) quit=true; // Увеличиваем TTL до 255 param=255; if (!quit && (setsockopt(sdout, SOL_IP, IP_TTL, ¶m, sizeof(param)) != 0)) quit=true; // Переводим сокет в неблокируемый режим param=1; if (!quit && (ioctl(sdin, FIONBIO, ¶m) != 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
Спокойный
Администратор
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
Спокойный
Администратор
Offline
Пол:
Пролетал мимо
|
|
« Ответ #9 : 22-08-2006 15:17 » |
|
Оно то делает одно и тоже, только new намного меньше нужно писать. Твоя бы строчка выгледила бы так: icmp_data = new char[MAX_PACKET];
|
|
|
Записан
|
Не будите спашяго дракона. Джаффар (Коша)
|
|
|
sss
Специалист
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)
|
|
|
|