icmpsocket.c

来自「opennms得相关源码 请大家看看」· C语言 代码 · 共 1,026 行 · 第 1/2 页

C
1,026
字号
/* This file is part of the OpenNMS(R) Application. OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved. OpenNMS(R) is a derivative work, containing both original code, included code and modified code that was published under the GNU General Public License. Copyrights for modified and included code are below. OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. Modifications: 2004 Oct 27: Handle Darwin 10.2 gracefully. 2003 Sep 07: More Darwin tweaks. 2003 Apr 26: Fixes byteswap issues on Solaris x86. 2003 Mar 25: Used unt64_t instead of unsigned long long. 2003 Feb 15: Bugfixes for Darwin. 2003 Feb 11: Bugfixes for Darwin. 2003 Feb 10: Bugfixes for Darwin. 2003 Feb 09: ICMP response time on Darwin. 2003 Feb 02: Initial Darwin port. 2002 Nov 26: Fixed build issues on Solaris. 2002 Nov 13: Added response times for ICMP. Original code base Copyright (C) 1999-2001 Oculan Corp.  All rights reserved. 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. For more information contact:      OpenNMS Licensing       <license@opennms.org>      http://www.opennms.org/      http://www.opennms.com/ Tab Size = 8*/#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/socket.h>#if defined(__SOLARIS__) || defined (__FreeBSD__)# include <netinet/in_systm.h>#endif#if defined(__DARWIN__) #include <stdint.h># include <netinet/in_systm.h># include <AvailabilityMacros.h># ifndef MAC_OS_X_VERSION_10_3#  define socklen_t int# endif#endif#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h> #include <netdb.h>#include <errno.h>#if defined(__FreeBSD__)#include "byteswap.h"#include <sys/time.h>#endif#if defined(__DARWIN__)#include <sys/time.h>#include <architecture/byte_order.h>#endif#include <jni.h>#if defined(__DARWIN__) || defined(__SOLARIS__) || defined (__FreeBSD__)typedef struct ip iphdr_t;typedef struct icmp icmphdr_t;#define ihl ip_hl#elsetypedef struct iphdr iphdr_t;typedef struct icmphdr icmphdr_t;#endif#pragma export on#include "IcmpSocket.h"#pragma export reset/** * This macro is used to recover the current time * in milliseconds. */#ifndef CURRENTTIMEMILLIS#define CURRENTTIMEMILLIS(_dst_) \{				\	struct timeval tv;	\	gettimeofday(&tv,NULL); \	_dst_ = (uint64_t)tv.tv_sec * 1000UL + (uint64_t)tv.tv_usec / 1000UL; \}#endif/**  * This macro is used to recover the current time * in microseconds */#ifndef CURRENTTIMEMICROS#define CURRENTTIMEMICROS(_dst_) \{				\	struct timeval tv;	\	gettimeofday(&tv,NULL); \	_dst_ = (uint64_t)tv.tv_sec * 1000000UL + (uint64_t)tv.tv_usec; \}#endif/** * converts microseconds to milliseconds */#ifndef MICROS_TO_MILLIS# define MICROS_TO_MILLIS(_val_) ((_val_) / 1000UL)#endif/** * convert milliseconds to microseconds. */#ifndef MILLIS_TO_MICROS# define MILLIS_TO_MICROS(_val_) ((_val_) * 1000UL)#endif/** * This constant specifies the length of a  * time field in the buffer */#ifndef TIME_LENGTH# define TIME_LENGTH sizeof(uint64_t)#endif/** * Specifies the header offset and length */#ifndef ICMP_HEADER_OFFSET# define ICMP_HEADER_OFFSET 0# define ICMP_HEADER_LENGTH 8#endif/**  * specifies the offset of the sent time. */#ifndef SENTTIME_OFFSET# define SENTTIME_OFFSET (ICMP_HEADER_OFFSET + ICMP_HEADER_LENGTH)#endif/** * Sepcifies the offset of the received time. */#ifndef RECVTIME_OFFSET# define RECVTIME_OFFSET (SENTTIME_OFFSET + TIME_LENGTH)#endif/** * Specifies the offset of the thread identifer */#ifndef THREADID_OFFSET# define THREADID_OFFSET (RECVTIME_OFFSET + TIME_LENGTH)#endif/** * Specifies the offset of the round trip time */#ifndef RTT_OFFSET# define RTT_OFFSET (THREADID_OFFSET + TIME_LENGTH)#endif/** * specifies the magic tag and the offset/length of * the tag in the header. */#ifndef OPENNMS_TAG# define OPENNMS_TAG "OpenNMS!"# define OPENNMS_TAG_LEN 8# define OPENNMS_TAG_OFFSET (RTT_OFFSET + TIME_LENGTH)#endif/** * Macros for doing byte swapping */#ifndef ntohll# if defined(__DARWIN__)#  define ntohll(_x_) NXSwapBigLongLongToHost(_x_)# elif defined(__SOLARIS__)#  if defined(_LITTLE_ENDIAN)#   define ntohll(_x_) ((((uint64_t)ntohl((_x_) >> 32)) & 0xffffffff) | (((uint64_t)ntohl(_x_)) << 32))#   define htonll(x) ntohll(x)#  else#   define ntohll(_x_) (_x_)#  endif# elif defined(__FreeBSD__)#  define  ntohll(_x_) __bswap_64(_x_)# else#  define ntohll(_x_) __bswap_64(_x_)# endif#endif#ifndef htonll# if defined(__DARWIN__)#  define htonll(_x_) NXSwapHostLongLongToBig(_x_)# elif defined(__SOLARIS__)#  if defined(_LITTLE_ENDIAN)#   define htonll(_x_) ((htonl((_x_ >> 32) & 0xffffffff) | ((uint64_t) (htonl(_x_ & 0xffffffff)) << 32)))#  else#   define htonll(_x_) (_x_)#  endif# elif defined(__FreeBSD__)#  define  htonll(_x_) __bswap_64(_x_)# else#  define htonll(_x_) __bswap_64(_x_)# endif#endif/** * This routine is used to quickly compute the * checksum for a particular buffer. The checksum * is done with 16-bit quantities and padded with * zero if the buffer is not aligned on a 16-bit * boundry. * */staticunsigned short checksum(register unsigned short *p, register int sz){	register unsigned long sum = 0;	// need a 32-bit quantity	/*	 * interate over the 16-bit values and 	 * accumulate a sum.	 */	while(sz > 1)	{		sum += *p++;		sz  -= 2;	}	if(sz == 1) /* handle the odd byte out */	{		/*		 * cast the pointer to an unsigned char pointer,		 * dereference and premote to an unsigned short.		 * Shift in 8 zero bits and whalla the value		 * is padded!		 */		sum += ((unsigned short) *((unsigned char *)p)) << 8;	}	/*	 * Add back the bits that may have overflowed the 	 * "16-bit" sum. First add high order 16 to low	 * order 16, then repeat	 */	while(sum >> 16)		sum = (sum >> 16) + (sum & 0xffffUL);	sum = ~sum & 0xffffUL; 	return sum;}/** * Opens a new raw socket that is set to send * and receive the ICMP protocol. The protocol * for 'icmp' is looked up using the function * getprotobyname() and passed to the newly  * constructed socket. *  * If the socket fails to open then a negative * number will be returned to the caller. * */static int openIcmpSocket(){	int			fd = -1;	struct protoent * 	proto = getprotobyname("icmp");	if(proto != (struct protoent *)NULL)	{		fd = socket(AF_INET, SOCK_RAW, proto->p_proto);	}	return fd;}/** * This method is used to lookup the instances java.io.FileDescriptor * object and it's internal integer descriptor. This hidden integer * is used to store the opened ICMP socket handle that was  * allocated by the operating system. * * If the descriptor could not be recovered or has not been * set then a negative value is returned. * */static jint getIcmpFd(JNIEnv *env, jobject instance){	jclass	thisClass = NULL;	jclass	fdClass   = NULL;	jfieldID thisFdField    = NULL;	jobject  thisFdInstance = NULL;	jfieldID fdFdField = NULL;	jint	 fd_value  = -1;	/**	 * Find the class that describes ourself.	 */	thisClass = (*env)->GetObjectClass(env, instance);	if(thisClass == NULL)		goto end_getfd;	/**	 * Find the java.io.FileDescriptor class	 */	thisFdField = (*env)->GetFieldID(env, thisClass, "m_rawFd", "Ljava/io/FileDescriptor;");	if(thisFdField == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_getfd;	(*env)->DeleteLocalRef(env, thisClass);	thisClass = NULL;	/**	 * Get the instance of the FileDescriptor class from	 * the instance of ourself	 */	thisFdInstance = (*env)->GetObjectField(env, instance, thisFdField);	if(thisFdInstance == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_getfd;	/**	 * Get the class object for the java.io.FileDescriptor	 */	fdClass = (*env)->GetObjectClass(env, thisFdInstance);	if(fdClass == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_getfd;	/**	 * Get the field identifier for the primitive integer	 * that is part of the FileDescriptor class.	 */	fdFdField = (*env)->GetFieldID(env, fdClass, "fd", "I");	if(fdFdField == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_getfd;	(*env)->DeleteLocalRef(env, fdClass);	fdClass = NULL;	/**	 * Recover the value	 */	fd_value = (*env)->GetIntField(env, thisFdInstance, fdFdField);	(*env)->DeleteLocalRef(env, thisFdInstance);end_getfd:	/**	 * method complete, value is -1 unless the 	 * entire method is successful.	 */	return fd_value;}static void setIcmpFd(JNIEnv *env, jobject instance, jint fd_value){	jclass	thisClass = NULL;	jclass	fdClass   = NULL;	jfieldID thisFdField    = NULL;	jobject  thisFdInstance = NULL;	jfieldID fdFdField = NULL;	/**	 * Find the class that describes ourself.	 */	thisClass = (*env)->GetObjectClass(env, instance);	if(thisClass == NULL)		goto end_setfd;	/**	 * Find the java.io.FileDescriptor class	 */	thisFdField = (*env)->GetFieldID(env, thisClass, "m_rawFd", "Ljava/io/FileDescriptor;");	if(thisFdField == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_setfd;	(*env)->DeleteLocalRef(env, thisClass);	thisClass = NULL;	/**	 * Get the instance of the FileDescriptor class from	 * the instance of ourself	 */	thisFdInstance = (*env)->GetObjectField(env, instance, thisFdField);	if(thisFdInstance == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_setfd;	/**	 * Get the class object for the java.io.FileDescriptor	 */	fdClass = (*env)->GetObjectClass(env, thisFdInstance);	if(fdClass == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_setfd;	/**	 * Get the field identifier for the primitive integer	 * that is part of the FileDescriptor class.	 */	fdFdField = (*env)->GetFieldID(env, fdClass, "fd", "I");	if(fdFdField == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_setfd;	(*env)->DeleteLocalRef(env, fdClass);	fdClass = NULL;	/**	 * Set the value	 */	(*env)->SetIntField(env, thisFdInstance, fdFdField, fd_value);	(*env)->DeleteLocalRef(env, thisFdInstance);end_setfd:	/**	 * method complete, value is -1 unless the 	 * entire method is successful.	 */	return;}static jobject newInetAddress(JNIEnv *env, unsigned long addr){	char 		buf[32];	jclass		addrClass;	jmethodID	addrByNameMethodID;	jobject 	addrInstance = NULL;	jstring		addrString = NULL;#define BYTE_OF(_x, _i) ((_x >> (_i * 8)) & 0xff)	sprintf(buf,		"%d.%d.%d.%d",		BYTE_OF(addr, 3),		BYTE_OF(addr, 2),		BYTE_OF(addr, 1),		BYTE_OF(addr, 0));#undef BYTE_OF	/**	 * create the string	 */	addrString = (*env)->NewStringUTF(env, (const char *)buf);	if(addrString == NULL || (*env)->ExceptionOccurred(env))		goto end_inet;	/**	 * load the class	 */	addrClass = (*env)->FindClass(env, "java/net/InetAddress");	if(addrClass == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_inet;	/**	 * Find the static method	 */	addrByNameMethodID = (*env)->GetStaticMethodID(env,						       addrClass,						       "getByName",						       "(Ljava/lang/String;)Ljava/net/InetAddress;");	if(addrByNameMethodID == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_inet;	/*	 * Invoke it!	 */	addrInstance = (*env)->CallStaticObjectMethod(env,						      addrClass,						      addrByNameMethodID,						      addrString);	(*env)->DeleteLocalRef(env, addrClass);	(*env)->DeleteLocalRef(env, addrString);end_inet:	return addrInstance;}static unsigned long getInetAddress(JNIEnv *env, jobject instance){	jclass		addrClass = NULL;	jmethodID	addrArrayMethodID = NULL;	jbyteArray	addrData = NULL;	unsigned long	retAddr = 0UL;	/**	 * load the class	 */	addrClass = (*env)->GetObjectClass(env, instance);	if(addrClass == NULL || (*env)->ExceptionOccurred(env) != NULL)		goto end_inet;	/**	 * Find the method

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?