A voir également:
- C'est quoi un ping
- Avoir du ping expression ✓ - Forum Réseau
- C est quoi un ping??????? - Forum Réseau
- Ping défaillance générale - Forum Réseau
- Ping url ✓ - Forum Réseaux sociaux
- Port ping - Forum Windows
5 réponses
la commande "ping" permet de vérifier l'accessibilité d'une machine d'internet.
plus précisemment, en faisant un ping, tu envoies des messages de type Echo Request ICMP à un hôte que tu as précisé...
Voila voili
N3
@@ Petit Agité, Tous des Béruriers
Petit Bérurier, Tous des Agités @@
plus précisemment, en faisant un ping, tu envoies des messages de type Echo Request ICMP à un hôte que tu as précisé...
Voila voili
N3
@@ Petit Agité, Tous des Béruriers
Petit Bérurier, Tous des Agités @@
Compliqué tout ça! :)
Faisons simple.
Quand tu lances un ping sur le réseau style 'ping adresse IP' la machine cible (donc celle qui a cette adresse IP) répond par un pong.
Voilà voilà
$ je pense donc je sue $
Faisons simple.
Quand tu lances un ping sur le réseau style 'ping adresse IP' la machine cible (donc celle qui a cette adresse IP) répond par un pong.
Voilà voilà
$ je pense donc je sue $
Commande dos permettant de tester un réseau et son routage.
C:\WINDOWS>ping
Utilisation : ping [-t] [-a] [-n échos] [-l taille] [-f] [-i vie] [-v TypServ]
[-r NbSauts] [-s NbSauts] [[-j ListeHôtes] | [-k ListeHôtes]]
[-w Délai] ListeDestination
Options :
-t Envoie la requête ping sur l'hôte spécifié jusqu'à
interruption. Entrez Ctrl-Arrêt pour afficher les
statistiques et continuer, Ctrl-C pour arrêter.
-a Recherche les noms d'hôte à partir des adresses.
-n échos Nombre de requêtes d'écho à envoyer.
-l taille Envoie la taille du tampon.
-f Active l'indicateur Ne pas fragmenter dans le paquet.
-i vie Durée de vie.
-v TypServ Type de service.
-r NbSauts Enregistre l'itinéraire pour le nombre de sauts.
-s NbSauts Dateur pour le nombre de sauts.
-j ListeHôtes Itinéraire source libre parmi la liste d'hôtes.
-k ListeHôtes Itinéraire source strict parmi la liste d'hôtes.
-w Délai Délai d'attente pour chaque réponse, en millisecondes.
et ... Voili Voilou Voila !
C:\WINDOWS>ping
Utilisation : ping [-t] [-a] [-n échos] [-l taille] [-f] [-i vie] [-v TypServ]
[-r NbSauts] [-s NbSauts] [[-j ListeHôtes] | [-k ListeHôtes]]
[-w Délai] ListeDestination
Options :
-t Envoie la requête ping sur l'hôte spécifié jusqu'à
interruption. Entrez Ctrl-Arrêt pour afficher les
statistiques et continuer, Ctrl-C pour arrêter.
-a Recherche les noms d'hôte à partir des adresses.
-n échos Nombre de requêtes d'écho à envoyer.
-l taille Envoie la taille du tampon.
-f Active l'indicateur Ne pas fragmenter dans le paquet.
-i vie Durée de vie.
-v TypServ Type de service.
-r NbSauts Enregistre l'itinéraire pour le nombre de sauts.
-s NbSauts Dateur pour le nombre de sauts.
-j ListeHôtes Itinéraire source libre parmi la liste d'hôtes.
-k ListeHôtes Itinéraire source strict parmi la liste d'hôtes.
-w Délai Délai d'attente pour chaque réponse, en millisecondes.
et ... Voili Voilou Voila !
et...
les résultats:
Quand ça marche:
C:\WINDOWS>ping commentcamarche.net
Envoi d'une requête 'ping' sur commentcamarche.net [212.43.238.166] avec 32 octe
ts de données :
Réponse de 212.43.238.166 : octets=32 temps=42 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=42 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=41 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=829 ms TTL=58
Statistiques Ping pour 212.43.238.166:
Paquets : envoyés = 4, reçus = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en milli-secondes :
minimum = 41ms, maximum = 829ms, moyenne = 238ms
ou encore:
C:\WINDOWS>ping -a 213.193.1.2
Envoi d'une requête 'ping' sur core-2-loopback.multimania.net [213.193.1.2] avec
32 octets de données :
Réponse de 213.193.1.2 : octets=32 temps=44 ms TTL=249
Réponse de 213.193.1.2 : octets=32 temps=41 ms TTL=248
Réponse de 213.193.1.2 : octets=32 temps=43 ms TTL=249
Réponse de 213.193.1.2 : octets=32 temps=42 ms TTL=248
Statistiques Ping pour 213.193.1.2:
Paquets : envoyés = 4, reçus = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en milli-secondes :
minimum = 41ms, maximum = 44ms, moyenne = 42ms
ET.... Quand ça ne marche pas (adresse au pif)
C:\WINDOWS>ping 212.24.35.62
Envoi d'une requête 'ping' sur 212.24.35.62 avec 32 octets de données :
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Statistiques Ping pour 212.24.35.62:
Paquets : envoyés = 4, reçus = 0, perdus = 4 (perte 100%),
Durée approximative des boucles en milli-secondes :
minimum = 0ms, maximum = 0ms, moyenne = 0ms
et ... Voili Voilou Voila !
les résultats:
Quand ça marche:
C:\WINDOWS>ping commentcamarche.net
Envoi d'une requête 'ping' sur commentcamarche.net [212.43.238.166] avec 32 octe
ts de données :
Réponse de 212.43.238.166 : octets=32 temps=42 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=42 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=41 ms TTL=58
Réponse de 212.43.238.166 : octets=32 temps=829 ms TTL=58
Statistiques Ping pour 212.43.238.166:
Paquets : envoyés = 4, reçus = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en milli-secondes :
minimum = 41ms, maximum = 829ms, moyenne = 238ms
ou encore:
C:\WINDOWS>ping -a 213.193.1.2
Envoi d'une requête 'ping' sur core-2-loopback.multimania.net [213.193.1.2] avec
32 octets de données :
Réponse de 213.193.1.2 : octets=32 temps=44 ms TTL=249
Réponse de 213.193.1.2 : octets=32 temps=41 ms TTL=248
Réponse de 213.193.1.2 : octets=32 temps=43 ms TTL=249
Réponse de 213.193.1.2 : octets=32 temps=42 ms TTL=248
Statistiques Ping pour 213.193.1.2:
Paquets : envoyés = 4, reçus = 4, perdus = 0 (perte 0%),
Durée approximative des boucles en milli-secondes :
minimum = 41ms, maximum = 44ms, moyenne = 42ms
ET.... Quand ça ne marche pas (adresse au pif)
C:\WINDOWS>ping 212.24.35.62
Envoi d'une requête 'ping' sur 212.24.35.62 avec 32 octets de données :
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Délai d'attente de la demande dépassé.
Statistiques Ping pour 212.24.35.62:
Paquets : envoyés = 4, reçus = 0, perdus = 4 (perte 100%),
Durée approximative des boucles en milli-secondes :
minimum = 0ms, maximum = 0ms, moyenne = 0ms
et ... Voili Voilou Voila !
salut,
si tu veux mieux comprendre comment ça marche avec les sockets, voilà des sources d'1 programme "ping". Ca marche sous Linux et solaris.
==========================
/*
* P I N G . C
*/
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/igmp.h>
#include <ctype.h>
#include <netdb.h>
#define MAXWAIT 10 /* max time to wait for response, sec. */
#define MAXPACKET (65536-60-8) /* max packet size */
#define VERBOSE 1 /* verbose flag */
#define QUIET 2 /* quiet flag */
#define FLOOD 4 /* floodping flag */
#define RROUTE 8 /* record route flag */
#define PING_FILLED 16 /* is buffer filled? */
#define NUMERIC 32 /* don't do gethostbyaddr() calls */
#define INTERVAL 64 /* did user specify interval? */
#define NROUTES 9 /* number of record route slots */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define MULTICAST_NOLOOP 1 /* multicast options */
#define MULTICAST_TTL 2
#define MULTICAST_IF 4
/* MAX_DUP_CHK is the number of bits in received table, ie the */
/* maximum number of received sequence numbers we can keep track of. */
/* Change 128 to 8192 for complete accuracy... */
#define MAX_DUP_CHK 8 * 128
int mx_dup_ck = MAX_DUP_CHK;
char rcvd_tbl[ MAX_DUP_CHK / 8 ];
int nrepeats = 0;
#define A(bit) rcvd_tbl[ (bit>>3) ] /* identify byte in array */
#define B(bit) ( 1 << (bit & 0x07) ) /* identify bit in byte */
#define SET(bit) A(bit) |= B(bit)
#define CLR(bit) A(bit) &= (~B(bit))
#define TST(bit) (A(bit) & B(bit))
char *malloc();
u_char *packet;
int packlen;
int i, pingflags = 0, options, moptions;
extern int errno;
int s; /* Socket file descriptor */
struct hostent *hp; /* Pointer to host info */
struct timezone tz; /* leftover */
struct sockaddr whereto; /* Who to ping */
int datalen = 64-8; /* How much data */
#if defined(MULTICAST)
char usage[] = "Usage: \
ping [-dfnqrvRL] [-c count] [-s size] [-l preload] [-p pattern] [-i interval]\n\
[-T ttl] [-I addr] [-h] host\n";
#else
char usage[] = "Usage: \
ping [-dfnqrvR] [-c count] [-s size] [-l preload] [-p pattern] [-i interval]\n\
[-h] host\n";
#endif /* MULTICAST */
char *hostname;
char hnamebuf[MAXHOSTNAMELEN];
static u_char outpack[MAXPACKET];
int npackets=0;
int preload = 0; /* number of packets to "preload" */
int ntransmitted = 0; /* sequence # for outbound packets = #sent */
int ident;
unsigned interval=1; /* interval between packets */
int nreceived = 0; /* # of packets we got back */
int timing = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0; /* sum of all times, for doing average */
int finish(), catcher();
int bufspace = 48*1024;
int prefinish();
char *pr_addr();
char rspace[3+4*NROUTES+1]; /* record route space */
/*
* M A I N
*/
main(argc, argv)
char *argv[];
{
struct sockaddr_in from;
/* char **av = argv; */
struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
int c, k, on = 1, hostind = 0;
struct protoent *proto;
static u_char *datap = &outpack[8+sizeof(struct timeval)];
unsigned char ttl, loop;
struct in_addr ifaddr;
extern int optind;
extern char *optarg;
while ((c = getopt(argc, argv, "c:dfh:i:l:np:qrs:vRLT:I:")) != EOF)
switch(c) {
case 'c':
npackets = atoi(optarg);
break;
case 'd':
options |= SO_DEBUG;
break;
case 'f':
pingflags |= FLOOD;
break;
case 'h':
hostind = optind-1;
break;
case 'i': /* wait between sending packets */
interval = atoi(optarg);
if (interval == 0)
interval = 1;
pingflags |= INTERVAL;
break;
case 'l':
preload = atoi(optarg);
break;
case 'n':
pingflags |= NUMERIC;
break;
case 'p': /* fill buffer with user pattern */
pingflags |= PING_FILLED;
fill((char *)datap, optarg);
break;
case 'q':
pingflags |= QUIET;
break;
case 'r':
options |= SO_DONTROUTE;
break;
case 's': /* size of packet to send */
datalen = atoi(optarg);
break;
case 'v':
pingflags |= VERBOSE;
break;
case 'R':
pingflags |= RROUTE;
break;
#ifdef MULTICAST
case 'L':
moptions |= MULTICAST_NOLOOP;
loop = 0;
break;
case 'T':
moptions |= MULTICAST_TTL;
ttl = atoi(optarg);
if (ttl > 255 || ttl <= 0) {
printf("%s: ttl %s out of range\n",
argv[0], optarg);
exit(1);
}
break;
case 'I':
moptions |= MULTICAST_IF;
ifaddr.s_addr = inet_addr(optarg);
if (ifaddr.s_addr == (unsigned)-1) {
hp = gethostbyname(optarg);
if (hp) {
bcopy(hp->h_addr,
(caddr_t)&ifaddr,
hp->h_length);
} else {
printf("%s: bad address '%s'\n",
argv[0],
optarg);
exit(1);
}
}
break;
#endif /* MULTICAST */
default:
printf(usage);
exit(1);
}
if (hostind == 0) {
if (optind != argc-1) {
fprintf(stderr, usage);
exit(1);
} else hostind = optind;
}
bzero((char *)&whereto, sizeof(struct sockaddr) );
to->sin_family = AF_INET;
to->sin_addr.s_addr = inet_addr(argv[hostind]);
if(to->sin_addr.s_addr != (unsigned)-1) {
strcpy(hnamebuf, argv[hostind]);
hostname = hnamebuf;
} else {
hp = gethostbyname(argv[hostind]);
if (hp) {
to->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
strncpy( hnamebuf, hp->h_name, sizeof(hnamebuf)-1 );
hostname = hnamebuf;
} else {
printf("%s: unknown host %s\n", argv[0], argv[hostind]);
exit(1);
}
}
if ( (pingflags & FLOOD) && (pingflags & INTERVAL) ) {
fprintf(stderr, "ping: -f and -i incompatible options\n");
exit(1);
}
if (datalen > MAXPACKET) {
fprintf(stderr, "ping: packet size too large\n");
exit(1);
}
if (datalen >= sizeof(struct timeval)) /* can we time 'em? */
timing = 1;
packlen = datalen + 60 + 76; /* MAXIP + MAXICMP */
if( (packet = (u_char *)malloc((unsigned)packlen)) == NULL ) {
fprintf( stderr, "ping: malloc failed\n" );
exit(1);
}
if (!(pingflags & PING_FILLED)) {
for( k=8; k<datalen; k++) *datap++ = k;
}
ident = getpid() & 0xFFFF;
if ((proto = getprotobyname("icmp")) == NULL) {
fprintf(stderr, "icmp: unknown protocol\n");
exit(10);
}
if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
perror("ping: socket");
exit(5);
}
if (options & SO_DEBUG) {
(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &on, sizeof(on));
}
if (options & SO_DONTROUTE) {
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
}
/* Record Route option */
if( pingflags & RROUTE ) {
#ifdef IP_OPTIONS
rspace[IPOPT_OPTVAL] = IPOPT_RR;
rspace[IPOPT_OLEN] = sizeof(rspace)-1;
rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
if( setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0 ) {
perror( "Record route" );
exit( 42 );
}
#else
fprintf( stderr, "ping: record route not available on this machine.\n" );
exit( 42 );
#endif IP_OPTIONS
}
#ifdef MULTICAST
if (moptions & MULTICAST_NOLOOP) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, 1) == -1) {
perror ("can't disable multicast loopback");
exit(92);
}
}
if (moptions & MULTICAST_TTL) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, 1) == -1) {
perror ("can't set multicast time-to-live");
exit(93);
}
}
if (moptions & MULTICAST_IF) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
&ifaddr, sizeof(ifaddr)) == -1) {
perror ("can't set multicast source interface");
exit(94);
}
}
#endif MULTICAST
if(to->sin_family == AF_INET) {
printf("PING %s (%s): %d data bytes\n", hostname,
inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr), datalen);
} else {
printf("PING %s: %d data bytes\n", hostname, datalen );
}
/* When pinging the broadcast address, you can get a lot
* of answers. Doing something so evil is useful if you
* are trying to stress the ethernet, or just want to
* fill the arp cache to get some stuff for /etc/ethers.
*/
(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,
sizeof(bufspace));
signal( SIGINT, prefinish );
signal(SIGALRM, catcher);
/* fire off them quickies */
for(i=0; i < preload; i++)
pinger();
if(!(pingflags & FLOOD))
catcher(); /* start things going */
for (;;) {
int fromlen = sizeof (from);
int cc;
struct timeval timeout;
int fdmask = 1 << s;
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if(pingflags & FLOOD) {
pinger();
if( select(32, (fd_set *)&fdmask, (fd_set *)0, (fd_set *)0, &timeout) == 0)
continue;
}
if ( (cc=recvfrom(s, (char *)packet, packlen, 0, (struct sockaddr *)&from, &fromlen)) < 0) {
if( errno == EINTR )
continue;
perror("ping: recvfrom");
continue;
}
pr_pack( (char *)packet, cc, &from );
if (npackets && nreceived >= npackets)
finish();
}
/*NOTREACHED*/
}
/*
* C A T C H E R
*
* This routine causes another PING to be transmitted, and then
* schedules another SIGALRM for 1 second from now.
*
* Bug -
* Our sense of time will slowly skew (ie, packets will not be launched
* exactly at 1-second intervals). This does not affect the quality
* of the delay and loss statistics.
*/
catcher()
{
int waittime;
pinger();
signal(SIGALRM, catcher);
if (npackets == 0 || ntransmitted < npackets)
alarm(interval);
else {
if (nreceived) {
waittime = 2 * tmax / 1000;
if (waittime == 0)
waittime = 1;
} else
waittime = MAXWAIT;
signal(SIGALRM, finish);
alarm((unsigned)waittime);
}
}
/*
* P I N G E R
*
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
* and the sequence number is an ascending integer. The first 8 bytes
* of the data portion are used to hold a UNIX "timeval" struct in VAX
* byte-order, to compute the round-trip time.
*/
pinger()
{
register struct icmp *icp = (struct icmp *) outpack;
int i, cc;
register struct timeval *tp = (struct timeval *) &outpack[8];
icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
icp->icmp_cksum = 0;
icp->icmp_seq = htons((unsigned short)(ntransmitted++));
icp->icmp_id = ident; /* ID */
CLR( ntohs(icp->icmp_seq) % mx_dup_ck );
cc = datalen+8; /* skips ICMP portion */
if (timing)
gettimeofday( tp, &tz );
/* Compute ICMP checksum here */
icp->icmp_cksum = in_cksum( (u_short *)icp, cc );
/* cc = sendto(s, msg, len, flags, to, tolen) */
i = sendto( s, (char *)outpack, cc, 0, &whereto, sizeof(struct sockaddr) );
if( i < 0 || i != cc ) {
if( i<0 ) perror("sendto");
printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i );
fflush(stdout);
}
if( pingflags & FLOOD ) {
putchar('.');
fflush(stdout);
}
}
/*
* P R _ P A C K
*
* Print out the packet, if it came from us. This logic is necessary
* because ALL readers of the ICMP socket get a copy of ALL ICMP packets
* which arrive ('tis only fair). This permits multiple copies of this
* program to be run without having intermingled output (or statistics!).
*/
pr_pack( buf, cc, from )
char *buf;
int cc;
struct sockaddr_in *from;
{
struct ip *ip;
register struct icmp *icp;
register int i, j;
register u_char *cp,*dp;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
struct timeval tv;
struct timeval *tp;
int hlen, triptime, dupflag;
gettimeofday( &tv, &tz );
/* Check the IP header */
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
if( cc < hlen + ICMP_MINLEN ) {
if( pingflags & VERBOSE )
printf("packet too short (%d bytes) from %s\n", cc,
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
fflush(stdout);
return;
}
/* Now the ICMP part */
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
if( icp->icmp_type == ICMP_ECHOREPLY ) {
if( icp->icmp_id != ident )
return; /* 'Twas not our ECHO */
nreceived++;
if (timing) {
#ifndef icmp_data
tp = (struct timeval *)&icp->icmp_ip;
#else
tp = (struct timeval *)&icp->icmp_data[0];
#endif
tvsub( &tv, tp );
triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
tsum += triptime;
if( triptime < tmin )
tmin = triptime;
if( triptime > tmax )
tmax = triptime;
}
if ( TST(ntohs(icp->icmp_seq)%mx_dup_ck) ) {
nrepeats++, nreceived--;
dupflag=1;
} else {
SET(ntohs(icp->icmp_seq)%mx_dup_ck);
dupflag=0;
}
if( pingflags & QUIET )
return;
if( pingflags & FLOOD ) {
putchar('\b');
fflush(stdout);
} else {
printf("%d bytes from %s: icmp_seq=%d", cc,
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
ntohs(icp->icmp_seq) );
if ( dupflag ) printf(" DUP!");
printf(" ttl=%d", ip->ip_ttl);
if (timing)
printf(" time=%d ms", triptime );
/* check the data */
cp = (u_char*)&icp->icmp_data[8];
dp = &outpack[8+sizeof(struct timeval)];
for (i=8; i<datalen; i++, cp++, dp++) {
if (*cp != *dp) {
printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
i, *dp, *cp);
cp = (u_char*)&icp->icmp_data[0];
for (i=8; i<datalen; i++, cp++) {
if ((i%32) == 8)
printf("\n\t");
printf("%x ", *cp);
}
break;
}
}
}
} else {
/* We've got something other than an ECHOREPLY */
if( !(pingflags & VERBOSE) )
return;
printf("%d bytes from %s: ",
cc, pr_addr(from->sin_addr.s_addr) );
pr_icmph( icp );
}
/* Display any IP options */
cp = (u_char *)buf + sizeof(struct ip);
while (hlen > sizeof(struct ip) && (hlen >= 0)) { /* !ANSI C will */
register unsigned long l; /* force hlen to */
switch (*cp) { /* unsigned! */
case IPOPT_EOL:
hlen = 0;
break;
case IPOPT_LSRR:
printf("\nLSRR: ");
hlen -= 2;
j = *++cp;
++cp;
if (j > IPOPT_MINOFF) for (;;) {
l = *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
j -= 4;
if (j <= IPOPT_MINOFF)
break;
putchar('\n');
}
break;
case IPOPT_RR:
j = *++cp; /* get length */
i = *++cp; /* and pointer */
hlen -= 2;
if (i > j) i = j;
i -= IPOPT_MINOFF;
if (i <= 0)
continue;
if (i == old_rrlen
&& cp == (u_char *)buf + sizeof(struct ip) + 2
&& !bcmp((char *)cp, old_rr, i)
&& !(pingflags & FLOOD)) {
printf("\t(same route)");
i = ((i+3)/4)*4;
hlen -= i;
cp += i;
break;
}
old_rrlen = i;
bcopy((char *)cp, old_rr, i);
printf("\nRR: ");
for (;;) {
l = *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
i -= 4;
if (i <= 0)
break;
putchar('\n');
}
break;
case IPOPT_NOP:
printf("\nNOP");
break;
default:
printf("\nunknown option %x", *cp);
break;
}
hlen--;
cp++;
}
if (!(pingflags & FLOOD))
putchar('\n');
fflush(stdout);
}
/*
* I N _ C K S U M
*
* Checksum routine for Internet Protocol family headers (C Version)
*
*/
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* 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);
}
/*
* T V S U B
*
* Subtract 2 timeval structs: out = out - in.
*
* Out is assumed to be >= in.
*/
tvsub( out, in )
register struct timeval *out, *in;
{
if( (out->tv_usec -= in->tv_usec) < 0 ) {
out->tv_sec--;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}
/* On the first SIGINT, allow any outstanding packets to dribble in */
prefinish()
{
if (nreceived >= ntransmitted /* quit now if caught up */
|| nreceived == 0) /* or if remote is dead */
finish();
signal(SIGINT, finish); /* do this only the 1st time */
npackets = ntransmitted+1; /* let the normal limit work */
}
/*
* F I N I S H
*
* Print out statistics, and give up.
* Heavily buffered STDIO is used here, so that all the statistics
* will be written with 1 sys-write call. This is nice when more
* than one copy of the program is running on a terminal; it prevents
* the statistics output from becomming intermingled.
*/
finish()
{
putchar('\n');
fflush(stdout);
printf("\n----%s PING Statistics----\n", hostname );
printf("%d packets transmitted, ", ntransmitted );
printf("%d packets received, ", nreceived );
if (nrepeats) printf("+%d duplicates, ", nrepeats );
if (ntransmitted)
if( nreceived > ntransmitted)
printf("-- somebody's printing up packets!");
else
printf("%d%% packet loss",
(int) (((ntransmitted-nreceived)*100) /
ntransmitted));
printf("\n");
if (nreceived && timing)
printf("round-trip (ms) min/avg/max = %d/%d/%d\n",
tmin,
tsum / (nreceived + nrepeats),
tmax );
fflush(stdout);
exit(0);
}
/*
* Print a descriptive string about an ICMP header.
*/
pr_icmph( icp )
struct icmp *icp;
{
switch( icp->icmp_type ) {
case ICMP_ECHOREPLY:
printf("Echo Reply\n");
/* XXX ID + Seq + Data */
break;
case ICMP_UNREACH:
switch( icp->icmp_code ) {
case ICMP_UNREACH_NET:
printf("Destination Net Unreachable\n");
break;
case ICMP_UNREACH_HOST:
printf("Destination Host Unreachable\n");
break;
case ICMP_UNREACH_PROTOCOL:
printf("Destination Protocol Unreachable\n");
break;
case ICMP_UNREACH_PORT:
printf("Destination Port Unreachable\n");
break;
case ICMP_UNREACH_NEEDFRAG:
printf("frag needed and DF set\n");
break;
case ICMP_UNREACH_SRCFAIL:
printf("Source Route Failed\n");
break;
default:
printf("Dest Unreachable, Bad Code: %d\n", icp->icmp_code );
break;
}
/* Print returned IP header information */
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_SOURCEQUENCH:
printf("Source Quench\n");
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_REDIRECT:
switch( icp->icmp_code ) {
case ICMP_REDIRECT_NET:
printf("Redirect Network");
break;
case ICMP_REDIRECT_HOST:
printf("Redirect Host");
break;
case ICMP_REDIRECT_TOSNET:
printf("Redirect Type of Service and Network");
break;
case ICMP_REDIRECT_TOSHOST:
printf("Redirect Type of Service and Host");
break;
default:
printf("Redirect, Bad Code: %d", icp->icmp_code );
break;
}
printf(" (New addr: 0x%08x)\n", icp->icmp_hun.ih_gwaddr );
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_ECHO:
printf("Echo Request\n");
/* XXX ID + Seq + Data */
break;
case ICMP_TIMXCEED:
switch( icp->icmp_code ) {
case ICMP_TIMXCEED_INTRANS:
printf("Time to live exceeded\n");
break;
case ICMP_TIMXCEED_REASS:
printf("Frag reassembly time exceeded\n");
break;
default:
printf("Time exceeded, Bad Code: %d\n", icp->icmp_code );
break;
}
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_PARAMPROB:
printf("Parameter problem: pointer = 0x%02x\n",
icp->icmp_hun.ih_pptr );
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_TSTAMP:
printf("Timestamp\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_TSTAMPREPLY:
printf("Timestamp Reply\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_IREQ:
printf("Information Request\n");
/* XXX ID + Seq */
break;
case ICMP_IREQREPLY:
printf("Information Reply\n");
/* XXX ID + Seq */
break;
#ifdef ICMP_MASKREQ
case ICMP_MASKREQ:
printf("Address Mask Request\n");
break;
#endif
#ifdef ICMP_MASKREPLY
case ICMP_MASKREPLY:
printf("Address Mask Reply\n");
break;
#endif
default:
printf("Bad ICMP type: %d\n", icp->icmp_type);
}
}
/*
* Print an IP header with options.
*/
pr_iph( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;
hlen = ip->ip_hl << 2;
cp = (unsigned char *)ip + 20; /* point to options */
printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n");
printf(" %1x %1x %02x %04x %04x",
ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id );
printf(" %1x %04x", ((ip->ip_off)&0xe000)>>13, (ip->ip_off)&0x1fff );
printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum );
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
/* dump and option bytes */
while( hlen-- > 20 ) {
printf( "%02x", *cp++ );
}
printf("\n");
}
/*
* Return an ascii host address
* as a dotted quad and optionally with a hostname
*/
char *
pr_addr( l )
unsigned long l;
{
struct hostent *hp;
static char buf[80];
if( (pingflags & NUMERIC) || (hp = gethostbyaddr((char *)&l, 4, AF_INET)) == NULL )
sprintf( buf, "%s", inet_ntoa(*(struct in_addr *)&l) );
else
sprintf( buf, "%s (%s)", hp->h_name, inet_ntoa(*(struct in_addr *)&l) );
return( buf );
}
/*
* Dump some info on a returned (via ICMP) IP packet.
*/
pr_retip( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;
pr_iph( ip );
hlen = ip->ip_hl << 2;
cp = (unsigned char *)ip + hlen;
if( ip->ip_p == 6 ) {
printf( "TCP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
} else if( ip->ip_p == 17 ) {
printf( "UDP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
}
}
fill(bp, patp)
char *bp, *patp;
{
register int ii,jj,kk;
char *cp;
int pat[16];
for (cp=patp; *cp; cp++)
if (!isxdigit(*cp)) {
printf("\"-p %s\" ???: ", patp);
printf("patterns must be specified as hex digits\n");
exit(1);
}
ii = sscanf(patp,
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
&pat[0], &pat[1], &pat[2], &pat[3],
&pat[4], &pat[5], &pat[6], &pat[7],
&pat[8], &pat[9], &pat[10], &pat[11],
&pat[12], &pat[13], &pat[14], &pat[15]);
if (ii > 0)
for (kk=0; kk<=MAXPACKET-(8+ii); kk+=ii)
for (jj=0; jj<ii; jj++)
bp[jj+kk] = pat[jj];
if (!(pingflags & QUIET)) {
printf("PATTERN: 0x");
for (jj=0; jj<ii; jj++)
printf("%02x", bp[jj]&0xFF);
printf("\n");
}
}
===============================
Si tu regardes un peu, y a moyen de faire un ping of death...
a+
mat
si tu veux mieux comprendre comment ça marche avec les sockets, voilà des sources d'1 programme "ping". Ca marche sous Linux et solaris.
==========================
/*
* P I N G . C
*/
#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/signal.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/igmp.h>
#include <ctype.h>
#include <netdb.h>
#define MAXWAIT 10 /* max time to wait for response, sec. */
#define MAXPACKET (65536-60-8) /* max packet size */
#define VERBOSE 1 /* verbose flag */
#define QUIET 2 /* quiet flag */
#define FLOOD 4 /* floodping flag */
#define RROUTE 8 /* record route flag */
#define PING_FILLED 16 /* is buffer filled? */
#define NUMERIC 32 /* don't do gethostbyaddr() calls */
#define INTERVAL 64 /* did user specify interval? */
#define NROUTES 9 /* number of record route slots */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#define MULTICAST_NOLOOP 1 /* multicast options */
#define MULTICAST_TTL 2
#define MULTICAST_IF 4
/* MAX_DUP_CHK is the number of bits in received table, ie the */
/* maximum number of received sequence numbers we can keep track of. */
/* Change 128 to 8192 for complete accuracy... */
#define MAX_DUP_CHK 8 * 128
int mx_dup_ck = MAX_DUP_CHK;
char rcvd_tbl[ MAX_DUP_CHK / 8 ];
int nrepeats = 0;
#define A(bit) rcvd_tbl[ (bit>>3) ] /* identify byte in array */
#define B(bit) ( 1 << (bit & 0x07) ) /* identify bit in byte */
#define SET(bit) A(bit) |= B(bit)
#define CLR(bit) A(bit) &= (~B(bit))
#define TST(bit) (A(bit) & B(bit))
char *malloc();
u_char *packet;
int packlen;
int i, pingflags = 0, options, moptions;
extern int errno;
int s; /* Socket file descriptor */
struct hostent *hp; /* Pointer to host info */
struct timezone tz; /* leftover */
struct sockaddr whereto; /* Who to ping */
int datalen = 64-8; /* How much data */
#if defined(MULTICAST)
char usage[] = "Usage: \
ping [-dfnqrvRL] [-c count] [-s size] [-l preload] [-p pattern] [-i interval]\n\
[-T ttl] [-I addr] [-h] host\n";
#else
char usage[] = "Usage: \
ping [-dfnqrvR] [-c count] [-s size] [-l preload] [-p pattern] [-i interval]\n\
[-h] host\n";
#endif /* MULTICAST */
char *hostname;
char hnamebuf[MAXHOSTNAMELEN];
static u_char outpack[MAXPACKET];
int npackets=0;
int preload = 0; /* number of packets to "preload" */
int ntransmitted = 0; /* sequence # for outbound packets = #sent */
int ident;
unsigned interval=1; /* interval between packets */
int nreceived = 0; /* # of packets we got back */
int timing = 0;
int tmin = 999999999;
int tmax = 0;
int tsum = 0; /* sum of all times, for doing average */
int finish(), catcher();
int bufspace = 48*1024;
int prefinish();
char *pr_addr();
char rspace[3+4*NROUTES+1]; /* record route space */
/*
* M A I N
*/
main(argc, argv)
char *argv[];
{
struct sockaddr_in from;
/* char **av = argv; */
struct sockaddr_in *to = (struct sockaddr_in *) &whereto;
int c, k, on = 1, hostind = 0;
struct protoent *proto;
static u_char *datap = &outpack[8+sizeof(struct timeval)];
unsigned char ttl, loop;
struct in_addr ifaddr;
extern int optind;
extern char *optarg;
while ((c = getopt(argc, argv, "c:dfh:i:l:np:qrs:vRLT:I:")) != EOF)
switch(c) {
case 'c':
npackets = atoi(optarg);
break;
case 'd':
options |= SO_DEBUG;
break;
case 'f':
pingflags |= FLOOD;
break;
case 'h':
hostind = optind-1;
break;
case 'i': /* wait between sending packets */
interval = atoi(optarg);
if (interval == 0)
interval = 1;
pingflags |= INTERVAL;
break;
case 'l':
preload = atoi(optarg);
break;
case 'n':
pingflags |= NUMERIC;
break;
case 'p': /* fill buffer with user pattern */
pingflags |= PING_FILLED;
fill((char *)datap, optarg);
break;
case 'q':
pingflags |= QUIET;
break;
case 'r':
options |= SO_DONTROUTE;
break;
case 's': /* size of packet to send */
datalen = atoi(optarg);
break;
case 'v':
pingflags |= VERBOSE;
break;
case 'R':
pingflags |= RROUTE;
break;
#ifdef MULTICAST
case 'L':
moptions |= MULTICAST_NOLOOP;
loop = 0;
break;
case 'T':
moptions |= MULTICAST_TTL;
ttl = atoi(optarg);
if (ttl > 255 || ttl <= 0) {
printf("%s: ttl %s out of range\n",
argv[0], optarg);
exit(1);
}
break;
case 'I':
moptions |= MULTICAST_IF;
ifaddr.s_addr = inet_addr(optarg);
if (ifaddr.s_addr == (unsigned)-1) {
hp = gethostbyname(optarg);
if (hp) {
bcopy(hp->h_addr,
(caddr_t)&ifaddr,
hp->h_length);
} else {
printf("%s: bad address '%s'\n",
argv[0],
optarg);
exit(1);
}
}
break;
#endif /* MULTICAST */
default:
printf(usage);
exit(1);
}
if (hostind == 0) {
if (optind != argc-1) {
fprintf(stderr, usage);
exit(1);
} else hostind = optind;
}
bzero((char *)&whereto, sizeof(struct sockaddr) );
to->sin_family = AF_INET;
to->sin_addr.s_addr = inet_addr(argv[hostind]);
if(to->sin_addr.s_addr != (unsigned)-1) {
strcpy(hnamebuf, argv[hostind]);
hostname = hnamebuf;
} else {
hp = gethostbyname(argv[hostind]);
if (hp) {
to->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
strncpy( hnamebuf, hp->h_name, sizeof(hnamebuf)-1 );
hostname = hnamebuf;
} else {
printf("%s: unknown host %s\n", argv[0], argv[hostind]);
exit(1);
}
}
if ( (pingflags & FLOOD) && (pingflags & INTERVAL) ) {
fprintf(stderr, "ping: -f and -i incompatible options\n");
exit(1);
}
if (datalen > MAXPACKET) {
fprintf(stderr, "ping: packet size too large\n");
exit(1);
}
if (datalen >= sizeof(struct timeval)) /* can we time 'em? */
timing = 1;
packlen = datalen + 60 + 76; /* MAXIP + MAXICMP */
if( (packet = (u_char *)malloc((unsigned)packlen)) == NULL ) {
fprintf( stderr, "ping: malloc failed\n" );
exit(1);
}
if (!(pingflags & PING_FILLED)) {
for( k=8; k<datalen; k++) *datap++ = k;
}
ident = getpid() & 0xFFFF;
if ((proto = getprotobyname("icmp")) == NULL) {
fprintf(stderr, "icmp: unknown protocol\n");
exit(10);
}
if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
perror("ping: socket");
exit(5);
}
if (options & SO_DEBUG) {
(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, &on, sizeof(on));
}
if (options & SO_DONTROUTE) {
(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &on, sizeof(on));
}
/* Record Route option */
if( pingflags & RROUTE ) {
#ifdef IP_OPTIONS
rspace[IPOPT_OPTVAL] = IPOPT_RR;
rspace[IPOPT_OLEN] = sizeof(rspace)-1;
rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
if( setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, sizeof(rspace)) < 0 ) {
perror( "Record route" );
exit( 42 );
}
#else
fprintf( stderr, "ping: record route not available on this machine.\n" );
exit( 42 );
#endif IP_OPTIONS
}
#ifdef MULTICAST
if (moptions & MULTICAST_NOLOOP) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
&loop, 1) == -1) {
perror ("can't disable multicast loopback");
exit(92);
}
}
if (moptions & MULTICAST_TTL) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, 1) == -1) {
perror ("can't set multicast time-to-live");
exit(93);
}
}
if (moptions & MULTICAST_IF) {
if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
&ifaddr, sizeof(ifaddr)) == -1) {
perror ("can't set multicast source interface");
exit(94);
}
}
#endif MULTICAST
if(to->sin_family == AF_INET) {
printf("PING %s (%s): %d data bytes\n", hostname,
inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr), datalen);
} else {
printf("PING %s: %d data bytes\n", hostname, datalen );
}
/* When pinging the broadcast address, you can get a lot
* of answers. Doing something so evil is useful if you
* are trying to stress the ethernet, or just want to
* fill the arp cache to get some stuff for /etc/ethers.
*/
(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace,
sizeof(bufspace));
signal( SIGINT, prefinish );
signal(SIGALRM, catcher);
/* fire off them quickies */
for(i=0; i < preload; i++)
pinger();
if(!(pingflags & FLOOD))
catcher(); /* start things going */
for (;;) {
int fromlen = sizeof (from);
int cc;
struct timeval timeout;
int fdmask = 1 << s;
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if(pingflags & FLOOD) {
pinger();
if( select(32, (fd_set *)&fdmask, (fd_set *)0, (fd_set *)0, &timeout) == 0)
continue;
}
if ( (cc=recvfrom(s, (char *)packet, packlen, 0, (struct sockaddr *)&from, &fromlen)) < 0) {
if( errno == EINTR )
continue;
perror("ping: recvfrom");
continue;
}
pr_pack( (char *)packet, cc, &from );
if (npackets && nreceived >= npackets)
finish();
}
/*NOTREACHED*/
}
/*
* C A T C H E R
*
* This routine causes another PING to be transmitted, and then
* schedules another SIGALRM for 1 second from now.
*
* Bug -
* Our sense of time will slowly skew (ie, packets will not be launched
* exactly at 1-second intervals). This does not affect the quality
* of the delay and loss statistics.
*/
catcher()
{
int waittime;
pinger();
signal(SIGALRM, catcher);
if (npackets == 0 || ntransmitted < npackets)
alarm(interval);
else {
if (nreceived) {
waittime = 2 * tmax / 1000;
if (waittime == 0)
waittime = 1;
} else
waittime = MAXWAIT;
signal(SIGALRM, finish);
alarm((unsigned)waittime);
}
}
/*
* P I N G E R
*
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
* and the sequence number is an ascending integer. The first 8 bytes
* of the data portion are used to hold a UNIX "timeval" struct in VAX
* byte-order, to compute the round-trip time.
*/
pinger()
{
register struct icmp *icp = (struct icmp *) outpack;
int i, cc;
register struct timeval *tp = (struct timeval *) &outpack[8];
icp->icmp_type = ICMP_ECHO;
icp->icmp_code = 0;
icp->icmp_cksum = 0;
icp->icmp_seq = htons((unsigned short)(ntransmitted++));
icp->icmp_id = ident; /* ID */
CLR( ntohs(icp->icmp_seq) % mx_dup_ck );
cc = datalen+8; /* skips ICMP portion */
if (timing)
gettimeofday( tp, &tz );
/* Compute ICMP checksum here */
icp->icmp_cksum = in_cksum( (u_short *)icp, cc );
/* cc = sendto(s, msg, len, flags, to, tolen) */
i = sendto( s, (char *)outpack, cc, 0, &whereto, sizeof(struct sockaddr) );
if( i < 0 || i != cc ) {
if( i<0 ) perror("sendto");
printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i );
fflush(stdout);
}
if( pingflags & FLOOD ) {
putchar('.');
fflush(stdout);
}
}
/*
* P R _ P A C K
*
* Print out the packet, if it came from us. This logic is necessary
* because ALL readers of the ICMP socket get a copy of ALL ICMP packets
* which arrive ('tis only fair). This permits multiple copies of this
* program to be run without having intermingled output (or statistics!).
*/
pr_pack( buf, cc, from )
char *buf;
int cc;
struct sockaddr_in *from;
{
struct ip *ip;
register struct icmp *icp;
register int i, j;
register u_char *cp,*dp;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
struct timeval tv;
struct timeval *tp;
int hlen, triptime, dupflag;
gettimeofday( &tv, &tz );
/* Check the IP header */
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
if( cc < hlen + ICMP_MINLEN ) {
if( pingflags & VERBOSE )
printf("packet too short (%d bytes) from %s\n", cc,
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
fflush(stdout);
return;
}
/* Now the ICMP part */
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
if( icp->icmp_type == ICMP_ECHOREPLY ) {
if( icp->icmp_id != ident )
return; /* 'Twas not our ECHO */
nreceived++;
if (timing) {
#ifndef icmp_data
tp = (struct timeval *)&icp->icmp_ip;
#else
tp = (struct timeval *)&icp->icmp_data[0];
#endif
tvsub( &tv, tp );
triptime = tv.tv_sec*1000+(tv.tv_usec/1000);
tsum += triptime;
if( triptime < tmin )
tmin = triptime;
if( triptime > tmax )
tmax = triptime;
}
if ( TST(ntohs(icp->icmp_seq)%mx_dup_ck) ) {
nrepeats++, nreceived--;
dupflag=1;
} else {
SET(ntohs(icp->icmp_seq)%mx_dup_ck);
dupflag=0;
}
if( pingflags & QUIET )
return;
if( pingflags & FLOOD ) {
putchar('\b');
fflush(stdout);
} else {
printf("%d bytes from %s: icmp_seq=%d", cc,
inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
ntohs(icp->icmp_seq) );
if ( dupflag ) printf(" DUP!");
printf(" ttl=%d", ip->ip_ttl);
if (timing)
printf(" time=%d ms", triptime );
/* check the data */
cp = (u_char*)&icp->icmp_data[8];
dp = &outpack[8+sizeof(struct timeval)];
for (i=8; i<datalen; i++, cp++, dp++) {
if (*cp != *dp) {
printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
i, *dp, *cp);
cp = (u_char*)&icp->icmp_data[0];
for (i=8; i<datalen; i++, cp++) {
if ((i%32) == 8)
printf("\n\t");
printf("%x ", *cp);
}
break;
}
}
}
} else {
/* We've got something other than an ECHOREPLY */
if( !(pingflags & VERBOSE) )
return;
printf("%d bytes from %s: ",
cc, pr_addr(from->sin_addr.s_addr) );
pr_icmph( icp );
}
/* Display any IP options */
cp = (u_char *)buf + sizeof(struct ip);
while (hlen > sizeof(struct ip) && (hlen >= 0)) { /* !ANSI C will */
register unsigned long l; /* force hlen to */
switch (*cp) { /* unsigned! */
case IPOPT_EOL:
hlen = 0;
break;
case IPOPT_LSRR:
printf("\nLSRR: ");
hlen -= 2;
j = *++cp;
++cp;
if (j > IPOPT_MINOFF) for (;;) {
l = *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
j -= 4;
if (j <= IPOPT_MINOFF)
break;
putchar('\n');
}
break;
case IPOPT_RR:
j = *++cp; /* get length */
i = *++cp; /* and pointer */
hlen -= 2;
if (i > j) i = j;
i -= IPOPT_MINOFF;
if (i <= 0)
continue;
if (i == old_rrlen
&& cp == (u_char *)buf + sizeof(struct ip) + 2
&& !bcmp((char *)cp, old_rr, i)
&& !(pingflags & FLOOD)) {
printf("\t(same route)");
i = ((i+3)/4)*4;
hlen -= i;
cp += i;
break;
}
old_rrlen = i;
bcopy((char *)cp, old_rr, i);
printf("\nRR: ");
for (;;) {
l = *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
l = (l<<8) + *++cp;
if (l == 0)
printf("\t0.0.0.0");
else
printf("\t%s", pr_addr(ntohl(l)));
hlen -= 4;
i -= 4;
if (i <= 0)
break;
putchar('\n');
}
break;
case IPOPT_NOP:
printf("\nNOP");
break;
default:
printf("\nunknown option %x", *cp);
break;
}
hlen--;
cp++;
}
if (!(pingflags & FLOOD))
putchar('\n');
fflush(stdout);
}
/*
* I N _ C K S U M
*
* Checksum routine for Internet Protocol family headers (C Version)
*
*/
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* 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);
}
/*
* T V S U B
*
* Subtract 2 timeval structs: out = out - in.
*
* Out is assumed to be >= in.
*/
tvsub( out, in )
register struct timeval *out, *in;
{
if( (out->tv_usec -= in->tv_usec) < 0 ) {
out->tv_sec--;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}
/* On the first SIGINT, allow any outstanding packets to dribble in */
prefinish()
{
if (nreceived >= ntransmitted /* quit now if caught up */
|| nreceived == 0) /* or if remote is dead */
finish();
signal(SIGINT, finish); /* do this only the 1st time */
npackets = ntransmitted+1; /* let the normal limit work */
}
/*
* F I N I S H
*
* Print out statistics, and give up.
* Heavily buffered STDIO is used here, so that all the statistics
* will be written with 1 sys-write call. This is nice when more
* than one copy of the program is running on a terminal; it prevents
* the statistics output from becomming intermingled.
*/
finish()
{
putchar('\n');
fflush(stdout);
printf("\n----%s PING Statistics----\n", hostname );
printf("%d packets transmitted, ", ntransmitted );
printf("%d packets received, ", nreceived );
if (nrepeats) printf("+%d duplicates, ", nrepeats );
if (ntransmitted)
if( nreceived > ntransmitted)
printf("-- somebody's printing up packets!");
else
printf("%d%% packet loss",
(int) (((ntransmitted-nreceived)*100) /
ntransmitted));
printf("\n");
if (nreceived && timing)
printf("round-trip (ms) min/avg/max = %d/%d/%d\n",
tmin,
tsum / (nreceived + nrepeats),
tmax );
fflush(stdout);
exit(0);
}
/*
* Print a descriptive string about an ICMP header.
*/
pr_icmph( icp )
struct icmp *icp;
{
switch( icp->icmp_type ) {
case ICMP_ECHOREPLY:
printf("Echo Reply\n");
/* XXX ID + Seq + Data */
break;
case ICMP_UNREACH:
switch( icp->icmp_code ) {
case ICMP_UNREACH_NET:
printf("Destination Net Unreachable\n");
break;
case ICMP_UNREACH_HOST:
printf("Destination Host Unreachable\n");
break;
case ICMP_UNREACH_PROTOCOL:
printf("Destination Protocol Unreachable\n");
break;
case ICMP_UNREACH_PORT:
printf("Destination Port Unreachable\n");
break;
case ICMP_UNREACH_NEEDFRAG:
printf("frag needed and DF set\n");
break;
case ICMP_UNREACH_SRCFAIL:
printf("Source Route Failed\n");
break;
default:
printf("Dest Unreachable, Bad Code: %d\n", icp->icmp_code );
break;
}
/* Print returned IP header information */
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_SOURCEQUENCH:
printf("Source Quench\n");
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_REDIRECT:
switch( icp->icmp_code ) {
case ICMP_REDIRECT_NET:
printf("Redirect Network");
break;
case ICMP_REDIRECT_HOST:
printf("Redirect Host");
break;
case ICMP_REDIRECT_TOSNET:
printf("Redirect Type of Service and Network");
break;
case ICMP_REDIRECT_TOSHOST:
printf("Redirect Type of Service and Host");
break;
default:
printf("Redirect, Bad Code: %d", icp->icmp_code );
break;
}
printf(" (New addr: 0x%08x)\n", icp->icmp_hun.ih_gwaddr );
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_ECHO:
printf("Echo Request\n");
/* XXX ID + Seq + Data */
break;
case ICMP_TIMXCEED:
switch( icp->icmp_code ) {
case ICMP_TIMXCEED_INTRANS:
printf("Time to live exceeded\n");
break;
case ICMP_TIMXCEED_REASS:
printf("Frag reassembly time exceeded\n");
break;
default:
printf("Time exceeded, Bad Code: %d\n", icp->icmp_code );
break;
}
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_PARAMPROB:
printf("Parameter problem: pointer = 0x%02x\n",
icp->icmp_hun.ih_pptr );
#ifndef icmp_data
pr_retip( &icp->icmp_ip );
#else
pr_retip( (struct ip *)icp->icmp_data );
#endif
break;
case ICMP_TSTAMP:
printf("Timestamp\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_TSTAMPREPLY:
printf("Timestamp Reply\n");
/* XXX ID + Seq + 3 timestamps */
break;
case ICMP_IREQ:
printf("Information Request\n");
/* XXX ID + Seq */
break;
case ICMP_IREQREPLY:
printf("Information Reply\n");
/* XXX ID + Seq */
break;
#ifdef ICMP_MASKREQ
case ICMP_MASKREQ:
printf("Address Mask Request\n");
break;
#endif
#ifdef ICMP_MASKREPLY
case ICMP_MASKREPLY:
printf("Address Mask Reply\n");
break;
#endif
default:
printf("Bad ICMP type: %d\n", icp->icmp_type);
}
}
/*
* Print an IP header with options.
*/
pr_iph( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;
hlen = ip->ip_hl << 2;
cp = (unsigned char *)ip + 20; /* point to options */
printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n");
printf(" %1x %1x %02x %04x %04x",
ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id );
printf(" %1x %04x", ((ip->ip_off)&0xe000)>>13, (ip->ip_off)&0x1fff );
printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum );
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
/* dump and option bytes */
while( hlen-- > 20 ) {
printf( "%02x", *cp++ );
}
printf("\n");
}
/*
* Return an ascii host address
* as a dotted quad and optionally with a hostname
*/
char *
pr_addr( l )
unsigned long l;
{
struct hostent *hp;
static char buf[80];
if( (pingflags & NUMERIC) || (hp = gethostbyaddr((char *)&l, 4, AF_INET)) == NULL )
sprintf( buf, "%s", inet_ntoa(*(struct in_addr *)&l) );
else
sprintf( buf, "%s (%s)", hp->h_name, inet_ntoa(*(struct in_addr *)&l) );
return( buf );
}
/*
* Dump some info on a returned (via ICMP) IP packet.
*/
pr_retip( ip )
struct ip *ip;
{
int hlen;
unsigned char *cp;
pr_iph( ip );
hlen = ip->ip_hl << 2;
cp = (unsigned char *)ip + hlen;
if( ip->ip_p == 6 ) {
printf( "TCP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
} else if( ip->ip_p == 17 ) {
printf( "UDP: from port %d, to port %d (decimal)\n",
(*cp*256+*(cp+1)), (*(cp+2)*256+*(cp+3)) );
}
}
fill(bp, patp)
char *bp, *patp;
{
register int ii,jj,kk;
char *cp;
int pat[16];
for (cp=patp; *cp; cp++)
if (!isxdigit(*cp)) {
printf("\"-p %s\" ???: ", patp);
printf("patterns must be specified as hex digits\n");
exit(1);
}
ii = sscanf(patp,
"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
&pat[0], &pat[1], &pat[2], &pat[3],
&pat[4], &pat[5], &pat[6], &pat[7],
&pat[8], &pat[9], &pat[10], &pat[11],
&pat[12], &pat[13], &pat[14], &pat[15]);
if (ii > 0)
for (kk=0; kk<=MAXPACKET-(8+ii); kk+=ii)
for (jj=0; jj<ii; jj++)
bp[jj+kk] = pat[jj];
if (!(pingflags & QUIET)) {
printf("PATTERN: 0x");
for (jj=0; jj<ii; jj++)
printf("%02x", bp[jj]&0xFF);
printf("\n");
}
}
===============================
Si tu regardes un peu, y a moyen de faire un ping of death...
a+
mat
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
les messages icmp echo:*
Message d'écho et de "réponse à écho"
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identificateur | Numéro de Séquence |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ...
+-+-+-+-+-
Champs IP :
Adresses : L'adresse de la source dans un message d'écho doit être le destinataire du message de "réponse à écho". Pour constituer un message de réponse à écho, il suffit d'inverser les adresses de source et de destination, et de mettre code type à 0, puis enfin de recalculer le Checksum.
Champs ICMP :
Type : 8 = écho;
0 = réponse à écho.
Code : 0
Checksum : Le complément à un sur 16 bits de la somme des compléments à un du message ICMP. Lors du calcul du Checksum, le champ destiné à recevoir ce Checksum sera laissé à zéro. Si la longueur totale du message est un nombre impair d'octets, le calcul du Checksum se fera en ajoutant un dernier octet à zéro de bourrage en fin de message. Ce mécanisme de Checksum sera changé dans le futur.
Identificateur : Si le code = 0, un identificateur permettant d'associer l'écho et la réponse à l'écho, peut être nul.
Numéro de séquence : Si le code = 0, un numéro de séquence permettant d'associer l'écho et sa réponse. Peut être nul.
Description
Les données reçues dans un message d'écho doivent être réémises dans la réponse à l'écho. L'identificateur et le numéro de séquence peuvent être utilisés par l'émetteur du message d'écho afin d'associer facilement l'écho et sa réponse. Par exemple, l'identificateur peut être utilisé comme l'est un port pour TCP ou UDP, identifiant ainsi une session, et le numéro de séquence incrémenté pour chaque message d'écho envoyé. Le "miroir" respectera ces deux valeurs pour renvoyer le retour.
Les messages de code 0 peuvent provenir d'un routeur ou d'un hôte.
*(extrait de la rfc 792 sur icmp):
http://www.eisti.fr/doc/norm/rfc792/792.htm
Puisqu'on est un peu dans la déconne :-))
et ... Voili Voilou Voila !
Message d'écho et de "réponse à écho"
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identificateur | Numéro de Séquence |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ...
+-+-+-+-+-
Champs IP :
Adresses : L'adresse de la source dans un message d'écho doit être le destinataire du message de "réponse à écho". Pour constituer un message de réponse à écho, il suffit d'inverser les adresses de source et de destination, et de mettre code type à 0, puis enfin de recalculer le Checksum.
Champs ICMP :
Type : 8 = écho;
0 = réponse à écho.
Code : 0
Checksum : Le complément à un sur 16 bits de la somme des compléments à un du message ICMP. Lors du calcul du Checksum, le champ destiné à recevoir ce Checksum sera laissé à zéro. Si la longueur totale du message est un nombre impair d'octets, le calcul du Checksum se fera en ajoutant un dernier octet à zéro de bourrage en fin de message. Ce mécanisme de Checksum sera changé dans le futur.
Identificateur : Si le code = 0, un identificateur permettant d'associer l'écho et la réponse à l'écho, peut être nul.
Numéro de séquence : Si le code = 0, un numéro de séquence permettant d'associer l'écho et sa réponse. Peut être nul.
Description
Les données reçues dans un message d'écho doivent être réémises dans la réponse à l'écho. L'identificateur et le numéro de séquence peuvent être utilisés par l'émetteur du message d'écho afin d'associer facilement l'écho et sa réponse. Par exemple, l'identificateur peut être utilisé comme l'est un port pour TCP ou UDP, identifiant ainsi une session, et le numéro de séquence incrémenté pour chaque message d'écho envoyé. Le "miroir" respectera ces deux valeurs pour renvoyer le retour.
Les messages de code 0 peuvent provenir d'un routeur ou d'un hôte.
*(extrait de la rfc 792 sur icmp):
http://www.eisti.fr/doc/norm/rfc792/792.htm
Puisqu'on est un peu dans la déconne :-))
et ... Voili Voilou Voila !