Files
recycled-ni-neutrino/src/system/ping.cpp
martii 1aa1acce45 gui/nfs: implement mac address lookup
Conflicts:
	src/gui/moviebrowser.cpp
	src/gui/nfs.cpp


Origin commit data
------------------
Branch: ni/coolstream
Commit: 706ea95092
Author: martii <m4rtii@gmx.de>
Date: 2013-06-29 (Sat, 29 Jun 2013)



------------------
This commit was generated by Migit
2014-09-15 14:04:20 +04:00

285 lines
6.0 KiB
C++

/**
* 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.
*
*/
#include "ping.h"
#ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
#endif /*EXIT_SUCCESS*/
#ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
#endif /*EXIT_FAILURE*/
#define MAXPACKET 65535
#define PKTSIZE 64
#define HDRLEN ICMP_MINLEN
#define DATALEN (PKTSIZE-HDRLEN)
#define MAXDATA (MAXPKT-HDRLEN-TIMLEN)
#define DEF_TIMEOUT 5
static int ident = 0;
static int timo = 2;
static int rrt;
static int sock = -1;
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 );
}
int
send_ping( const char *host, struct sockaddr_in *taddr )
{
int len;
int ss;
unsigned char buf[ HDRLEN + DATALEN ];
struct protoent *proto;
struct hostent *hp;
struct icmp *icp;
unsigned short last;
len = HDRLEN + DATALEN;
if(( proto = getprotobyname( "icmp" )) == NULL ){
return -1;
}
if(( hp = gethostbyname( host )) != NULL ){
memmove( &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((sock < 0) && ( sock = socket( AF_INET, SOCK_RAW, proto->p_proto )) < 0 ){
#ifdef DEBUG
perror( "sock" );
#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( sock, buf, sizeof( buf ), 0,
(struct sockaddr*)taddr, sizeof( *taddr ))) < 0 ){
#ifdef DEBUG
perror( "sock" );
#endif/*DEBUG*/
close( sock );
sock = -1;
return -2;
}
if( ss != len ){
#ifdef DEBUG
perror( "malformed packet" );
#endif/*DEBUG*/
close( sock );
sock = -1;
return -2;
}
return 0;
}
static int
recv_ping( struct sockaddr_in *taddr )
{
int len;
socklen_t from;
int nf, cc;
unsigned char buf[ HDRLEN + DATALEN ];
//struct icmp *icp;
struct sockaddr_in faddr;
struct timeval to;
fd_set readset, writeset;
to.tv_sec = timo / 100000;
to.tv_usec = ( timo - ( to.tv_sec * 100000 ) ) * 10;
FD_ZERO( &readset );
FD_ZERO( &writeset );
FD_SET( 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( sock + 1, &readset, &writeset, NULL, &to )) < 0 ){
#ifdef DEBUG
perror( "select" );
#endif/*DEBUG*/
exit( EXIT_FAILURE );
}
if( nf == 0 ){
return -1;
}
len = HDRLEN + DATALEN;
from = sizeof( faddr );
cc = recvfrom( sock, buf, len, 0, (struct sockaddr*)&faddr, &from );
if( cc < 0 ){
exit( EXIT_FAILURE );
}
//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;
}
/**
* elapsed_time
* returns an int value for the difference
* between now and starttime in milliseconds.
*/
static int
elapsed_time( struct timeval *starttime ){
struct timeval *newtime;
int elapsed;
newtime = (struct timeval*)malloc( 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 );
}
free(newtime);
return( elapsed );
}
static int
myping(const std::string &hostname, int t, struct sockaddr_in *sa = NULL)
{
int err;
struct sockaddr_in _sa;
struct timeval mytime;
if (!sa)
sa = &_sa;
ident = getpid() & 0xFFFF;
if( t == 0 ) timo = 2;
else timo = t;
(void) gettimeofday( &mytime, (struct timezone *)NULL);
if(( err = send_ping( hostname.c_str(), sa )) < 0 ){
return err;
}
do{
if(( rrt = elapsed_time( &mytime )) > timo * 1000 ){
close( sock );
sock = -1;
return 0;
}
} while( recv_ping(sa));
close( sock );
sock = -1;
return 1;
}
int
pinghost(const std::string &hostname, std::string *ip)
{
struct sockaddr_in sa;
int res = myping( hostname, 0, &sa);
if (ip) {
char *p = inet_ntoa(sa.sin_addr);
*ip = p ? std::string(p) : "";
}
return res;
}
int
pingthost(const std::string &hostname, int t)
{
return myping( hostname, t );
}
int
tpinghost(const std::string &hostname)
{
int ret;
if(( ret = myping( hostname, 0 )) > 0 )
return rrt;
else
return ret;
}
int
tpingthost(const std::string &hostname, int t )
{
int ret;
if(( ret = myping( hostname, t )) > 0 )
return rrt;
else
return ret;
}