123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /**
- * PING module
- *
- * Copyright (C) 2001 Jeffrey Fulmer <jdfulmer@armstrong.com>
- * This file is part of LIBPING
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * --
- *
- * This code has been lightly modified to adapt it in the Netsukuku source
- * code.
- */
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include <pthread.h>
- #include <stdlib.h>
-
- #include "libping.h"
- #include "xmalloc.h"
- #include "log.h"
-
- #define MAXPACKET 65535
- #define PKTSIZE 64
- #define HDRLEN ICMP_MINLEN
- #define DATALEN (PKTSIZE-HDRLEN)
- #define MAXDATA (MAXPKT-HDRLEN-TIMLEN)
- #define DEF_TIMEOUT 5
-
- struct ping_priv
- ping_priv_default(void)
- {
- struct ping_priv datum;
- datum.ident = IDENT_DEFAULT;
- datum.timo = TIMO_DEFAULT;
- return datum;
- }
-
- /**
- * elapsed_time
- * returns an int value for the difference
- * between now and starttime in milliseconds.
- */
- int
- elapsed_time(struct timeval *starttime)
- {
- struct timeval *newtime;
- int elapsed;
- newtime = (struct timeval *) xmalloc(sizeof(struct timeval));
- gettimeofday(newtime, NULL);
- elapsed = 0;
-
- if ((newtime->tv_usec - starttime->tv_usec) > 0) {
- elapsed += (newtime->tv_usec - starttime->tv_usec) / 1000;
- } else {
- elapsed +=
- (1000000 + newtime->tv_usec - starttime->tv_usec) / 1000;
- newtime->tv_sec--;
- }
- if ((newtime->tv_sec - starttime->tv_sec) > 0) {
- elapsed += 1000 * (newtime->tv_sec - starttime->tv_sec);
- }
- if (elapsed < 1)
- elapsed = 1;
-
- xfree(newtime);
- return (elapsed);
- }
-
- void
- JOEfreeprotoent(struct protoent *p)
- {
- char **a;
- xfree(p->p_name);
- if (p->p_aliases != NULL) {
- for (a = p->p_aliases; *a != NULL; a++) {
- xfree(*a);
- }
- }
- xfree(p);
- }
-
- void
- JOEfreehostent(struct hostent *h)
- {
- char **p;
-
- xfree(h->h_name);
- if (h->h_aliases != NULL) {
- for (p = h->h_aliases; *p != NULL; ++p)
- xfree(*p);
- xfree(h->h_aliases);
- }
- if (h->h_addr_list != NULL) {
- for (p = h->h_addr_list; *p != NULL; ++p)
- xfree(*p);
- xfree(h->h_addr_list);
- }
- xfree(h);
- }
-
- static int
- in_checksum(u_short * buf, int len)
- {
- register long sum = 0;
- u_short answer = 0;
-
- while (len > 1) {
- sum += *buf++;
- len -= 2;
- }
-
- if (len == 1) {
- *(u_char *) (&answer) = *(u_char *) buf;
- sum += answer;
- }
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- answer = ~sum;
-
- return (answer);
-
- }
-
- static int
- send_ping(const char *host, struct sockaddr_in *taddr,
- struct ping_priv *datum)
- {
- int len;
- int ss;
- unsigned char buf[HDRLEN + DATALEN];
-
- #define PROTO_BUF_LEN 1024
- char proto_buf[PROTO_BUF_LEN];
- struct protoent *proto = NULL;
- struct protoent proto_datum;
-
- struct hostent *hp = NULL;
- struct hostent hent;
- int herrno;
- char hbf[9000];
- #if defined(_AIX)
- char *aixbuf;
- char *probuf;
- int rc;
- #endif/*_AIX*/
-
- struct icmp *icp;
- unsigned short last;
-
- len = HDRLEN + DATALEN;
-
- #if defined(__GLIBC__)
- /* for systems using GNU libc */
- getprotobyname_r("icmp", &proto_datum, proto_buf, PROTO_BUF_LEN,
- &proto);
- if ((gethostbyname_r(host, &hent, hbf, sizeof(hbf), &hp, &herrno) < 0)) {
- hp = NULL;
- }
- #elif defined(sun)
- /* Solaris 5++ */
- proto =
- getprotobyname_r("icmp", &proto_datum, proto_buf, PROTO_BUF_LEN);
- hp = gethostbyname_r(host, &hent, hbf, sizeof(hbf), &herrno);
- #elif defined(_AIX)
- aixbuf = (char *) xmalloc(9000);
- probuf = (char *) xmalloc(9000);
- rc = getprotobyname_r("icmp", &proto,
- (struct protoent_data *) (probuf +
- sizeof(struct
- protoent)));
- rc = gethostbyname_r(host, (struct hostent *) aixbuf,
- (struct hostent_data *) (aixbuf +
- sizeof(struct hostent)));
- hp = (struct hostent *) aixbuf;
- #elif ( defined(hpux) || defined(__osf__) )
- proto = getprotobyname("icmp");
- hp = gethostbyname(host);
- herrno = h_errno;
- #else
- /* simply hoping that get*byname is thread-safe */
- proto = getprotobyname("icmp");
- hp = gethostbyname(host);
- herrno = h_errno;
- #endif /*OS SPECIFICS */
-
- if (proto == NULL) {
- return -1;
- }
-
- if (hp != NULL) {
- memcpy(&taddr->sin_addr, hp->h_addr_list[0],
- sizeof(taddr->sin_addr));
- taddr->sin_port = 0;
- taddr->sin_family = AF_INET;
- } else if (inet_aton(host, &taddr->sin_addr) == 0) {
- return -1;
- }
-
- last = ntohl(taddr->sin_addr.s_addr) & 0xFF;
- if ((last == 0x00) || (last == 0xFF)) {
- return -1;
- }
-
- if ((datum->sock = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
- #ifdef DEBUG
- debug(DBG_NORMAL, ERROR_MSG "sock: %s" ERROR_POS, strerror(errno));
- #endif /*DEBUG*/
- return -2;
- }
-
- icp = (struct icmp *) buf;
- icp->icmp_type = ICMP_ECHO;
- icp->icmp_code = 0;
- icp->icmp_cksum = 0;
- icp->icmp_id = getpid() & 0xFFFF;
- icp->icmp_cksum = in_checksum((u_short *) icp, len);
-
- if ((ss = sendto(datum->sock, buf, sizeof(buf), 0,
- (struct sockaddr *) taddr, sizeof(*taddr))) < 0) {
- #ifdef DEBUG
- debug(DBG_NORMAL, ERROR_MSG "sock: %s" ERROR_POS, strerror(errno));
- #endif /*DEBUG*/
- return -2;
- }
- if (ss != len) {
- #ifdef DEBUG
- debug(DBG_NORMAL, ERROR_MSG "sock: %s" ERROR_POS, strerror(errno));
- #endif /*DEBUG*/
- return -2;
- }
- #if defined(_AIX)
- xfree(aixbuf);
- xfree(probuf);
- #endif
- /* JOEfreeprotoent( proto ); */
- /* JOEfreeprotoent( &proto_datum ); */
- /* JOEfreehostent( hp ); */
- /* JOEfreehostent( &hent ); */
- return 0;
- }
-
- static int
- recv_ping(struct sockaddr_in *taddr, struct ping_priv *datum)
- {
- int len;
- int from;
- int nf, cc;
- unsigned char buf[HDRLEN + DATALEN];
- //struct icmp *icp;
- struct sockaddr_in faddr;
- struct timeval to;
- fd_set readset;
-
- to.tv_sec = datum->timo / 100000;
- to.tv_usec = (datum->timo - (to.tv_sec * 100000)) * 10;
-
- FD_ZERO(&readset);
- FD_SET(datum->sock, &readset);
- /* we use select to see if there is any activity
- on the socket. If not, then we've requested an
- unreachable network and we'll time out here. */
- if ((nf = select(datum->sock + 1, &readset, NULL, NULL, &to)) < 0) {
- datum->rrt = -4;
- #ifdef DEBUG
- debug(DBG_NORMAL, ERROR_MSG "sock: %s" ERROR_POS, strerror(errno));
- #endif /*DEBUG*/
- return 0;
- }
- if (nf == 0) {
- return -1;
- }
-
- len = HDRLEN + DATALEN;
- from = sizeof(faddr);
-
- cc = recvfrom(datum->sock, buf, len, 0, (struct sockaddr *) &faddr,
- (socklen_t *) & from);
- if (cc < 0) {
- datum->rrt = -4;
- #ifdef DEBUG
- debug(DBG_NORMAL, ERROR_MSG "sock: %s" ERROR_POS, strerror(errno));
- #endif /*DEBUG*/
- return 0;
- }
-
- //icp = (struct icmp *) (buf + HDRLEN + DATALEN);
- if (faddr.sin_addr.s_addr != taddr->sin_addr.s_addr) {
- return 1;
- }
- /*****
- if( icp->icmp_id != ( getpid() & 0xFFFF )){
- printf( "id: %d\n", icp->icmp_id );
- return 1;
- }
- *****/
- return 0;
- }
-
- int
- myping(const char *hostname, int t, struct ping_priv *datum)
- {
- int err;
- int rrt;
- struct sockaddr_in sa;
- struct timeval mytime;
-
- datum->ident = getpid() & 0xFFFF;
-
- if (t == 0)
- datum->timo = 2;
- else
- datum->timo = t;
-
- datum->rrt = 0;
-
- (void) gettimeofday(&mytime, (struct timezone *) NULL);
- if ((err = send_ping(hostname, &sa, datum)) < 0) {
- close(datum->sock);
- return err;
- }
- do {
- rrt = elapsed_time(&mytime);
- if (datum->rrt < 0)
- return 0;
- datum->rrt = rrt;
- if (datum->rrt > datum->timo * 1000) {
- close(datum->sock);
- return 0;
- }
- } while (recv_ping(&sa, datum));
- close(datum->sock);
-
- return 1;
- }
-
- int
- pinghost(const char *hostname)
- {
- struct ping_priv datum = ping_priv_default();
- return myping(hostname, 0, &datum);
- }
-
- int
- pingthost(const char *hostname, int t)
- {
- struct ping_priv datum = ping_priv_default();
- return myping(hostname, t, &datum);
- }
-
- int
- tpinghost(const char *hostname)
- {
- int ret;
- struct ping_priv datum = ping_priv_default();
-
- ret = myping(hostname, 0, &datum);
- if (ret > 0)
- ret = datum.rrt;
- return ret;
- }
-
- int
- tpingthost(const char *hostname, int t)
- {
- int ret;
- struct ping_priv datum = ping_priv_default();
-
- ret = myping(hostname, t, &datum);
- if (ret > 0)
- ret = datum.rrt;
- return ret;
- }
|