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 + -
显示快捷键?