¿Cómo capturar paquetes inalcanzables del puerto ICMP? Gracias.
#include
#include
#include
# include
#include
//#define WIN32_LEAN_AND_MEAN
#define IP_RECORD_ROUTE 0X7 //Indica que la ruta debe ser registrado
#define DEF_PACKET_SIZE 32 //Tamaño de datagrama predeterminado
#define MAX_PACKET 1024 //Longitud máxima del datagrama ICMP
#define MAX_IP_HDR_SIZE 60 //IP máxima Longitud del encabezado
#define ICMP_ECHO 8 //Solicitud de eco
#define ICMP_ECHOREPLY 0 //Respuesta de eco
#define ICMP_MIN 8 //Tamaño mínimo del datagrama ICMP
void InitPing();
void UserHelp();
void GetArgments();
USHORT CheckSum(USHORT *buffer,int size);
void FillICMPData(char *icmp_data,int datasize);
void FreeRes();
void DecodeIPOptions(char *buf, int bytes) ;
void DecodeICMPHeader(char *buf,int bytes,SOCKADDR_IN *from);
void PingTest(int timeout);
void CalSpeed ();
typedef struct _iphdr
{
unsigned int h_len:4; //longitud del encabezado ip
unsigned int version: 4; Versión de IP
unsigned char tos; //Tipo de servicio
unsigned short total_len; //Longitud total del datagrama
unsigned short ident; /p>
unsigned short frag_flags; //Indicadores de fragmentos
unsigned char ttl;
unsigned char proto; //Tipo de protocolo
suma de comprobación corta unsigned; ; //suma de verificación
unsigned int sourceIP; //source IP
unsigned int destIP; //dest IP
}IpHeader;
typedef estructura _icmphdr
{
> BYTE i_type; //Tipo de mensaje
BYTE i_code; //Número de código
USHORT i_cksum; //Suma de comprobación
USHORT i_id; /p>
USHORT i_seq; //número de serie
marca de tiempo ULONG;//marca de tiempo
}IcmpHeader;
typedef struct _ipoptionhdr
{
código de carácter unsigned; //Tipo de opción
unsigned char len; //Longitud de la opción
unsigned char ptr;
unsigned long addr[9]; //Lista de direcciones IP registradas
}IpOptionHeader;
#define n 5
SOCKET m_socket ;
IpOptionHeader IpOption;
SOCKADDR_IN DestAddr;
SOCKADDR_IN SourceAddr;
char *icmp_data;
p>char *recvbuf;
USHORT seq_no;
char *Ipdest;
int datasize;
BOOL RecordFlag
doble PacketNum;
BOOL SucessFlag;
char ipd[20];
DWORD tick;
int veces[n ];
Velocidad de flotación;
FILETIME inicio, fin;
duración larga;
int timeo=0
;/*WSADATA Esta estructura se utiliza para almacenar datos de Windows Sockets devueltos después de ser llamados por la función WSAStartup. Contiene datos ejecutados por Winsock.dll.
struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
iMaxSockets cortos sin firmar;
iMaxUdpDg corto sin firmar;
char *lpVendorInfo;
};
*/
void InitPing()
{
WSADATA wsaData;
icmp_data = NULL ;
seq_no = 0;
recvbuf = NULL;
RecordFlag = FALSE;
Ipdest = NULL;
datasize = DEF_PACKET_SIZE;
PacketNum = n;
SucessFlag = FALSE;
/*Para llamar a cualquier función API de Winsock en la aplicación,
En primer lugar, lo primero es completar la inicialización del servicio Winsock a través de la función WSAStartup, por lo que es necesario llamar a la función WSAStartup.
Los programas que utilizan Socket deben llamar a la función WSAStartup antes de utilizar Socket. El primer parámetro de esta función indica la versión de Socket solicitada por el programa.
El byte de orden superior indica la versión menor y el byte de orden inferior indica la versión principal que el sistema operativo usa. para devolver la información de versión de Socket solicitada.
Cuando una aplicación llama a la función WSAStartup, el sistema operativo busca la biblioteca de Socket correspondiente según la versión de Socket solicitada,
y luego vincula la biblioteca de Socket encontrada a la aplicación. Luego, la aplicación puede llamar a otras funciones de Socket en la biblioteca de Socket solicitada.
*/
memset(times,255,n*sizeof(times[0]));
if(WSAStartup(MAKEWORD(2,2) , &wsaData)!=0)
{
printf("WSAStartup() falló: %d\n",GetLastError());
}
m_socket = INVALID_SOCKET;
}
void UserHelp()
{
printf("UserHelp: ping -r
printf(" -r ruta de registro\n");
printf(" -n cantidad de registro\n" );
printf(" host de la máquina remota a Ping\n");
printf(" el tamaño de datos puede ser de hasta 1 KB\n");
Proceso de salida(-1);
}
void GetArgments()
{
scanf("%s",ipd) ;
Ipdest=ipd;
}
Suma de comprobación USHORT(USHORT *búfer, tamaño int)
{
unsigned long cksum=0;
while(size>1)
{
cksum+=*buffer++;
tamaño- =tamañode(USHORT);
}
if(tamaño)
{
cksum +=*(UCHAR*)buffer;
}
cksum = (cksum>>16)+ (cksum & 0xffff);
cksum +=(cksum>>16);
return (USHORT)(~cksum);
}
void FillICMPData(char *icmp_data, int datasize)
{
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_c
ksum = 0;
icmp_hdr->i_seq = 0;
datapart = icmp_data + sizeof(IcmpHeader);
memset(datapart,'E',datasize -sizeof(IcmpHeader));
}
void FreeRes()
{
if(m_socket != INVALID_SOCKET) p>
closesocket(m_socket);
HeapFree(GetProcessHeap(), 0, recvbuf);
HeapFree(GetProcessHeap(), 0, icmp_data);
WSACleanup();
return ;
}
void DecodeIPOptions(char *buf, int bytes)
{
IpOptionHeader *ipopt = NULL;
IN_ADDR inaddr;
int i;
HOSTENT *host = NULL;
ipopt = (IpOptionHeader *)(buf+20);
printf("RR: ");
for(i = 0; i<(ipopt->ptr/ 4)-1;i++)
{
inaddr.S_un.S_addr = ipopt->addr[i];
if(i!=0)
printf(" ");
host = gethostbyaddr((char *)&inaddr.S_un.S_addr,sizeof(inaddr.S_un.S_addr),AF_INET);
if(host)
printf("(%-15s) %s\n",inet_ntoa(inaddr),host->h_name);
else
printf("(%-15s)\n",inet_ntoa(inaddr));
}
return ;
}
void DecodeICMPHeader(char *buf,int bytes,SOCKADDR_IN *from)
{
IpHeader *iphdr = NULL;
IcmpHeader *icmphdr = NULL;
iphdrlen corto sin firmar;
// DWORD tick;
static int icmpcount =0;
iphdr = (IpHeader * )buf;
iphdrlen = iphdr->h_len * 4;
// tick = Ge
tTickCount();
if((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount))
DecodeIPOptions(buf,bytes);
if(bytes< iphdrlen + ICMP_MIN)
{
printf("Muy pocos bytes de %s\n",
inet_ntoa(from->sin_addr)); p> p>
}
icmphdr = (IcmpHeader*)(buf+iphdrlen);
if((icmphdr->i_type != ICMP_ECHOREPLY) )
{
printf("nonecho type %d recvd\n",icmphdr->i_type);
return ;
}
if(icmphdr->i_id != (USHORT)GetCurrentProcessId())
{
printf("¡el paquete de otra persona!\n");
return ;
}
SucessFlag = TRUE;
printf("%d bytes de %s:",bytes,inet_ntoa(from->sin_addr )) ;
printf("icmp_seq = %d. ",icmphdr->i_seq);
times[icmphdr->i_seq]=tick-icmphdr->marca de tiempo; p>
printf("hora: %d ms",tick-icmphdr->marca de tiempo);
printf("\n");
icmpcount++;
// Sleep(1000);
return ;
}
void PingTest(int timeout)
{
// int ret;
int readNum;
int writeNum;
int fromlen;
struct hostent *hp = NULL;
/*Crea un socket sin formato, que se utiliza para el protocolo ICMP*/
m_socket = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED );
/*Si la creación del socket no tiene éxito*/
if(m_socket == INVALID_SOCKET)
{
printf ( "WSASocket() falló: %d\n",WSAGetLastError());
retorno
;
}
/*Opciones de enrutamiento de registros
if(RecordFlag)
{
ZeroMemory(&IpOption ,sizeof(IpOption));
IpOption.code = IP_RECORD_ROUTE;
IpOption.ptr = 4;
IpOption.len = 39;
ret = setsockopt(m_socket, IPPROTO_IP,IP_OPTIONS,(char *)&IpOption,sizeof(IpOption));
if(ret== SOCKET_ERROR)
{
printf("setsockopt(IP_OPTIONS) falló: %d\n",WSAGetLastError());
}
}
*/
/*Establecer el valor del tiempo de espera de recepción*/
readNum = setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO,(char *)&timeout,sizeof(timeout));
if(readNum == SOCKET_ERROR)
{
printf("setsockopt(SO_RCVTIMEO) falló: %d\n",WSAGetLastError());
return ;
}
/*Establecer el valor de tiempo de espera para el envío*/
timeout=1000;
readNum = setsockopt(m_socket , SOL_SOCKET, SO_SNDTIMEO,(char *)&timeout,sizeof(timeout));
if(readNum == SOCKET_ERROR)
{
printf("setsockopt ( SO_SNDTIMEO) falló: %d\n",WSAGetLastError());
return ;
}
/*Inicializar la dirección de destino con ceros*/ p>
memset(&DestAddr,0,sizeof(DestAddr));
/*Establezca la familia de direcciones, lo que indica que se utiliza la familia de direcciones IP*/
DestAddr.sin_family = AF_INET;
if((DestAddr.sin_addr.s_addr = inet_addr(Ipdest))==INADDR_NONE)
{
/*Si el la entrada es un nombre de dominio, luego conviértala al formato de IP estándar, de lo contrario no se procesará */
if((hp=gethostbyname(Ipdest)) != NULL)
{
/*obtendrá La dirección IP está asignada a DestAddr*/
memcpy(&(DestAddr.sin_addr),hp->h_addr,hp->h_length);
/*Asigne el valor de la familia de direcciones al campo correspondiente en DestAddr*/
DestAddr.sin_family = hp->h_addrtype;
printf("DestAddr.sin_addr = %s\n",inet_ntoa(DestAddr.sin_addr));
}
else
{
printf("gethostbyname() falló: %d\n",WSAGetLastError());
return
}
}
/*El tamaño del datagrama debe incluir el encabezado ICMP*/
datasize +=sizeof( IcmpHeader);
// printf("datasize=%d\n",datasize);
icmp_data = (char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
recvbuf=(char *)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET);
if(!icmp_data)
{
printf(" HeapAlloc() falló:%d\n",GetLastError());
return ;
}
memset(icmp_data,0, MAX_PACKET);
FillICMPData(icmp_data,datasize);
while(1)
{
static int nCount = 0;
if(nCount++==PacketNum) //Salir mientras después de cinco pruebas
descanso;
((IcmpHeader*)icmp_data)->i_cksum = 0;
/*Establecer la hora de inicio*/
// GetSystemTimeAsFileTime(&beg);
((IcmpHeader*)icmp_data)->timestamp = timeGetTime();
((IcmpHeader*)icmp_data)->i_seq = seq_no++;
/*Calcular suma de comprobación*/
((IcmpHeader*)icmp_data)->i_cksum = CheckSum((USHORT *)icmp_data,datasize);
wri
teNum= sendto(m_socket, icmp_data, datasize, 0,(struct sockaddr*) &DestAddr,sizeof(DestAddr));
// printf("SendDataSize = %d\n",writeNum); p>
if(writeNum == SOCKET_ERROR)
{
if(WSAGetLastError()== WSAETIMEDOUT)
{
timeo=1;
printf("Se agotó el tiempo de envío\n");
continuar;
}
printf(" sendto() falló: %d\n",WSAGetLastError());
return ;
}
fromlen=sizeof(SourceAddr);
readNum=recvfrom(m_socket,recvbuf,MAX_PACKET, 0,(struct sockaddr*)&SourceAddr,&fromlen);
// printf("RecvDataSize = %d\n",readNum);
// tick=GetTickCount();
tick=timeGetTime();
// GetSystemTimeAsFileTime(&end);
// dur=100*(end.dwLowDateTime-beg.dwLowDateTime);
// printf("Hora: %ld us\n",dur/1000);
if(readNum == SOCKET_ERROR)
{
if(WSAGetLastError()== WSAETIMEDOUT)
{
timeo=1;
printf("Se agotó el tiempo de recepción\n");
continuar;
}
printf("recepción fallida: %d\n" ,WSAGetLastError());
return ;
}
DecodeICMPHeader(recvbuf,readNum,&SourceAddr);
}
printf("\nLos bytes de envío y recepción son %d B",writeNum+readNum);
}<
/p>
void CalSpeed()
{
int i;
int l=0;
int min= veces[0];
for(i=1;i { si(min>veces[i]) p> { min=veces[i]; l=i; } } // printf("\ntimes[l]====%d\n",times[l]); if(times[l]) { Velocidad = (float)(108)/times[l]; printf("\nEl TTL mínimo es %d ms",times[l]) ; printf("\nVelocidad estimada = %.2f KB/S\n\n",Velocidad); } else p> { printf("\nSu host y su host de destino están en la misma LAN\n"); } } int main() { printf("Ingrese el DIP del que desea hacer ping: "); InitPing(); GetArgments(); PingTest(1000); CalSpeed(); // Sleep(1000); // if(SucessFlag) // printf("\n¡Fin, tienes %.0f registros!\n",PacketNum); // else // printf("\nFin, ¡sin registro!"); FreeRes(); getchar(); devolver 0; }