Funkce ping

computer at optimit.cz computer at optimit.cz
Thu Apr 17 16:40:41 CEST 1997


> mam takovy, mozna dost blby dotaz. Jak pracuje program (prikaz) ping.
> Hledal jsem to ve vsech moznych priruckach, ale nic jsem nenasel.

Pracuje pomerne jednoduse. Program samotny je dost slozity, pro svoji
potrebu na lokalni (!) siti jsem si ping hodne upravil. Na Internetu
by vam to moc nefungovalo, ale jako ilustrace to postaci.

Pro ping se pouziva protokol ICMP (Internet Control Message Protocol),
popsany v RFC792. Strucny popis vysel v knizce
Pavel Smrha, Vladimir Rudolf: "Internetworking pomoci TCP/IP",
nakladatelstvi Kopp.

-------------------------------------------------------------
Petr Bravenec, computer at optimit.cz
-------------- next part --------------
/* Na detaily mrkni do rfc792 nebo do knizky
  "Internetworking pomoci TCP/IP" na stranku 37 */
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>

#ifdef SVR4
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef SVR3
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#endif

#include <netdb.h>
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <sys/file.h>
#ifndef SVR3
#include <stdlib.h>
#endif
#include <string.h>
#include <errno.h>

#ifdef Linux
#define icmp_type type
#define icmp_code code
#define icmp_cksum checksum
#define icmp_seq un.echo.sequence
#define icmp_id  un.echo.id
#endif

void   pinger ();
int    ping   ();
struct sockaddr whereto;
int    paclen=20;
int    ping_sock;
int    ident;

/******************************************************************************/
int ping (target)
char *target;
{
    struct protoent *proto;
    struct sockaddr_in from;
    struct sockaddr_in *to;
    int    fromlen;
    int    i,cc,hold;
    char   packet[1024];

    ident = getpid () & 0xFFFF;
    /**************************/
    /* Priprava struktur cile */
    to = (struct sockaddr_in *)&whereto;
    to->sin_family = AF_INET;
    to->sin_addr.s_addr = inet_addr (target);
    /* tady si zjistuji IP adresu pocitace - abych vedel, kam pingnout */
    if (to->sin_addr.s_addr == -1) {
	struct hostent  *hp;
	hp = gethostbyname (target);
	if (NULL == hp) {
	    fprintf (stderr,"Neznamy pocitac %s\n",target);
	    return 0;
	    }
	memcpy  (&to->sin_addr, hp->h_addr, hp->h_length);
	}
#if defined SVR3 || defined Linux
    }
#else
    /**************************/
    /* Pro ping je provozovan na specialnim protokolu ICMP */
    /* cili obchazi TCP i UDP (v /etc/services ho nenajdete) */
    if (NULL == (proto = getprotobyname ("icmp"))) {
	fprintf (stderr,"Ping: neznamy protokol ICMP\n");
	return 0;
	}
    if (0> (ping_sock = socket (AF_INET, SOCK_RAW, proto->p_proto))) {
	fprintf (stderr,"Ping: nejde vytvorit socket: %s\n",strerror(errno));
	return 0;
	}
    hold = 64;
    if (0 > setsockopt (ping_sock, SOL_SOCKET, SO_RCVBUF, (char *)&hold, sizeof (hold))) {
	fprintf (stderr,"Chyba setsockopt: %s\n",strerror(errno));
	return 0;
	}
    for (i=0; i<10; i++) {
	fd_set  re;
	struct timeval timo;
	FD_ZERO (&re);
	FD_SET  (ping_sock, &re);
	timo.tv_sec=1;
	timo.tv_usec=0;
	pinger ();                        /* posli na pocitac jeden pinganec */
	select (ping_sock+1,&re,NULL,NULL,&timo);  /* cekam 1s na odpoved */
                                                   /* skutecny ping ceka dele */
                                                   /* ja jsem na local net */
	if (FD_ISSET(ping_sock,&re)) {
	    struct icmphdr *icp;      /* precteme si, co se vratilo */
	    cc = recvfrom (ping_sock, packet, paclen, 0, (struct sockaddr *)&from, &fromlen);
	    if (0> cc) {
		fprintf (stderr,"Ping: recvfrom: %s\n",strerror(errno));
		}
	    icp = (struct icmphdr *)packet;
	    if (cc == 20 && icp->icmp_id==ident && icp->icmp_type==0) {
		close (ping_sock);
		return 1;
		}
	    }
	}
    close (ping_sock);
    return 0;
}

/******************************************************************************/
void pinger () {
    struct icmphdr *icp;
    char   outpack[1024];
    int    i;

    for (i=0; i<paclen; i++)
	outpack[i]=0xFF;
    icp = (struct icmphdr *)outpack;
    icp->icmp_type = ICMP_ECHO;
    icp->icmp_code = 0;
    icp->icmp_cksum = 0;
    icp->icmp_seq = 0;
    icp->icmp_id = ident;                   /* ID */
    i = sendto (ping_sock, icp, paclen, 0, &whereto, sizeof (struct sockaddr) );
    if (i!=paclen || i<0) {
	fprintf (stderr,"Ping: chyba odeslani paketu: %s\n",strerror(errno));
	}
}
#endif



More information about the net mailing list