📄 jpcap.c
字号:
#ifdef WIN32
#include<winsock2.h>
#include<iphlpapi.h>
#endif /* for WIN32 */
#include<jni.h>
#include<pcap.h>
//#include<net/bpf.h>
#ifndef WIN32
#include<sys/param.h>
#include<sys/socket.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<errno.h>
#define __FAVOR_BSD
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#ifndef SIOCGIFCONF
#include<sys/sockio.h>
#endif
#endif
#include<netinet/in_systm.h>
#include<netinet/ip.h>
#ifdef INET6
#ifndef WIN32
#define COMPAT_RFC2292
#include<netinet/ip6.h>
#include<netinet6/ah.h>
#else
typedef unsigned char u_int8_t;
typedef unsigned short u_int16_t;
typedef unsigned int u_int32_t;
typedef int pid_t;
#define IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options */
#define IPPROTO_IPV6 41 /* IPv6 header */
#define IPPROTO_ROUTING 43 /* IPv6 Routing header */
#define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
#define IPPROTO_ESP 50 /* encapsulating security payload */
#define IPPROTO_AH 51 /* authentication header */
#define IPPROTO_ICMPV6 58 /* ICMPv6 */
#define IPPROTO_NONE 59 /* IPv6 no next header */
#define IPPROTO_DSTOPTS 60 /* IPv6 Destination options */
#include<ws2tcpip.h>
#include<tpipv6.h>
#include<netinet/ip6.h>
#include<netinet6/ah.h>
#endif
#endif
#include"jpcap_JpcapCaptor.h"
#include"Jpcap_sub.h"
#include"Jpcap_ether.h"
const int offset_type[]={0,12,-1,-1,-1,-1,20,-1,-1,2,
#ifdef PCAP_FDDIPAD
19+PCAP_FDDIPAD,
#else
19,
#endif
6,-1,-1,5};
const int offset_data[]={4,14,-1,-1,-1,-1,22,-1,16,4,
#ifdef PCAP_FDDIPAD
21+PCAP_FDDIPAD,
#else
21,
#endif
8,0,24,24};
#define get_network_type(data,id) ntohs(*(u_short *)(data+offset_type[linktypes[id]]))
#define skip_datalink_header(data,id) (data+offset_data[linktypes[id]])
#define datalink_hlen(id) offset_data[linktypes[id]]
#define UNKNOWN_PROTO 0xffff
pcap_t *pcds[MAX_NUMBER_OF_INSTANCE];
JNIEnv *jni_envs[MAX_NUMBER_OF_INSTANCE];
char pcap_errbuf[PCAP_ERRBUF_SIZE][MAX_NUMBER_OF_INSTANCE];
jclass Jpcap=NULL,JpcapHandler,Interface,IAddress,Packet,DatalinkPacket,EthernetPacket,IPPacket,TCPPacket,UDPPacket,ICMPPacket,IPv6Option,ARPPacket,String,Thread,UnknownHostException,IOException;
jmethodID deviceConstMID,addressConstMID,handleMID,setPacketValueMID,setDatalinkPacketMID,
setPacketHeaderMID,setPacketDataMID,
setEthernetValueMID,setIPValueMID,setIPv4OptionMID,setIPv6ValueMID,addIPv6OptHdrMID,
setTCPValueMID,setTCPOptionMID,setUDPValueMID,
setICMPValueMID,setICMPIDMID,setICMPTimestampMID,setICMPRedirectIPMID,getICMPRedirectIPMID,
setICMPRouterAdMID,setV6OptValueMID,setV6OptOptionMID,setV6OptFragmentMID,
setV6OptRoutingMID,setV6OptAHMID,
setARPValueMID,
getSourceAddressMID,getDestinationAddressMID;
jfieldID jpcapID;
int linktypes[MAX_NUMBER_OF_INSTANCE];
bpf_u_int32 netnums[MAX_NUMBER_OF_INSTANCE],netmasks[MAX_NUMBER_OF_INSTANCE];
jobject jpcap_handlers[MAX_NUMBER_OF_INSTANCE];
char pcap_errbuf[PCAP_ERRBUF_SIZE][MAX_NUMBER_OF_INSTANCE];
void set_info(JNIEnv *env,jobject obj,pcap_t *pcd);
void set_Java_env(JNIEnv *);
void get_packet(struct pcap_pkthdr,u_char *,jobject *,int);
void dispatcher_handler(u_char *,const struct pcap_pkthdr *,const u_char *);
struct ip_packet *getIP(char *payload);
u_short analyze_ip(JNIEnv *env,jobject packet,u_char *data);
u_short analyze_tcp(JNIEnv *env,jobject packet,u_char *data);
void analyze_udp(JNIEnv *env,jobject packet,u_char *data);
void analyze_icmp(JNIEnv *env,jobject packet,u_char *data,u_short len);
#ifdef INET6
u_short analyze_ipv6(JNIEnv *env,jobject packet,u_char *data);
#endif
int analyze_arp(JNIEnv *env,jobject packet,u_char *data);
jobject analyze_datalink(JNIEnv *env,u_char *data,int linktype);
int getJpcapID(JNIEnv *env,jobject obj)
{
return GetIntField(Jpcap,obj,"ID");
}
jbyteArray getAddressByteArray(JNIEnv *env,struct sockaddr *addr)
{
jbyteArray array;
if(addr==NULL) return NULL;
switch(addr->sa_family){
case AF_INET:
array=(*env)->NewByteArray(env,4);
(*env)->SetByteArrayRegion(env,array,0,4,(jbyte *)&((struct sockaddr_in *)addr)->sin_addr);
break;
case AF_INET6:
array=(*env)->NewByteArray(env,16);
(*env)->SetByteArrayRegion(env,array,0,16,(jbyte *)&((struct sockaddr_in6 *)addr)->sin6_addr);
break;
default:
//printf("AF:%d\n",addr->sa_family);
return NULL;
break;
}
return array;
}
/**
Get Interface List
**/
JNIEXPORT jobjectArray JNICALL Java_jpcap_JpcapCaptor_getDeviceList
(JNIEnv *env, jclass cl)
{
pcap_if_t *alldevs;
pcap_if_t *d;
pcap_addr_t *a;
pcap_t *tmp_pcap;
char errbuf[PCAP_ERRBUF_SIZE];
int i=0,j=0,k=0;
jobjectArray devices=NULL;
jobjectArray addresses=NULL;
jobject device=NULL;
jobject address=NULL;
int linktype;
jstring lname,ldesc;
#ifdef WIN32
u_long size=0;
PIP_INTERFACE_INFO pInfo = NULL;
MIB_IFROW MibIfRow;
char **devnames;
char *p1,*p2,*p3;
#else
int sd;
struct ifreq ifr;
u_char buf[6];
#endif
Interface=FindClass("jpcap/NetworkInterface");
deviceConstMID=(*env)->GetMethodID(env,Interface,"<init>","(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[B[Ljpcap/NetworkInterfaceAddress;)V");
IAddress=FindClass("jpcap/NetworkInterfaceAddress");
addressConstMID=(*env)->GetMethodID(env,IAddress,"<init>","([B[B[B[B)V");
(*env)->ExceptionDescribe(env);
/* Retrieve the device list */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
return NULL;
}
//count # of devices
for(i=0,d=alldevs;d;d=d->next,i++);
//create array
devices=(*env)->NewObjectArray(env,(jsize)i,Interface,NULL);
#ifdef WIN32
//obtain necessary size
GetInterfaceInfo(NULL, &size);
//allocate memory
pInfo = (PIP_INTERFACE_INFO) malloc (size);
if(GetInterfaceInfo(pInfo, &size)!=NO_ERROR){
Throw(IOException,"GetInterfaceInfo failed.");
return NULL;
}
#endif
/* Set Interface data */
for(i=0,d=alldevs;d;d=d->next)
{
jbyteArray mac=(*env)->NewByteArray(env,6);
//set mac
#ifdef WIN32
// compare the device names obtained from Pcap and from IP Helper
// in order to identify MAC address
// since device name differs in 9x and NT/XP, compare name
// from the end (not sure if this works in every case. I hope it does..)
p1=d->name;
while(*p1!=0) p1++; //find the end
//convert wchar to char
devnames=(char **)malloc(sizeof(char *)*pInfo->NumAdapters);
for(j=0;j<pInfo->NumAdapters;j++){
size=WideCharToMultiByte(0,0,pInfo->Adapter[j].Name,-1,NULL,0,NULL,NULL);
devnames[j]=(char *)malloc(size);
WideCharToMultiByte(0,0,pInfo->Adapter[j].Name,-1,devnames[j],size,NULL,NULL);
//printf("%s\n",devnames[j]);
}
for(j=0;j<pInfo->NumAdapters;j++){
p2=p1;
p3=devnames[j];
while(*p3!=0) p3++; //find the end
k=0;
//printf("%s,%s:%d\n",d->name,devnames[j],j);
while(*p2==*p3){
p2--; p3--; k++;
//printf("%c,%c,%d\n",*p2,*p3,k);
}
if(k<30) continue;
//found! set MAC address
MibIfRow.dwIndex=pInfo->Adapter[j].Index;
GetIfEntry(&MibIfRow);
(*env)->SetByteArrayRegion(env,mac,0,MibIfRow.dwPhysAddrLen,MibIfRow.bPhysAddr);
}
#else
/* make socket */
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
Throw(IOException,"cannot open socket.");
return NULL; // error: can't create socket.
}
/* set interface name (lo, eth0, eth1,..) */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name,d->name, IFNAMSIZ);
/* get a Get Interface Hardware Address */
ioctl(sd, SIOCGIFHWADDR, &ifr);
close(sd);
(*env)->SetByteArrayRegion(env,mac,0,6,ifr.ifr_ifru.ifru_hwaddr.sa_data);
#endif
//count # of addresses
for(j=0,a=d->addresses;a;a=a->next)
if(getAddressByteArray(env,a->addr)) j++;
//create array of addresses
addresses=(*env)->NewObjectArray(env,(jsize)j,IAddress,NULL);
//set address data
for(j=0,a=d->addresses;a;a=a->next)
{
jbyteArray addr=getAddressByteArray(env,a->addr);
if(addr){
address=(*env)->NewObject(env,IAddress,addressConstMID,
addr,getAddressByteArray(env,a->netmask),
getAddressByteArray(env,a->broadaddr),getAddressByteArray(env,a->dstaddr));
(*env)->SetObjectArrayElement(env,addresses,j++,address);
}
}
//get datalink name
tmp_pcap=pcap_open_live(d->name,0,0,1000,errbuf);
if(tmp_pcap!=NULL){
linktype=pcap_datalink(tmp_pcap);
lname=NewString(pcap_datalink_val_to_name(linktype));
ldesc=NewString(pcap_datalink_val_to_description(linktype));
pcap_close(tmp_pcap);
}else{
lname=NewString("Unknown");
ldesc=NewString("Unknown");
}
device=(*env)->NewObject(env,Interface,deviceConstMID,NewString(d->name),
NewString(d->description),(d->flags&PCAP_IF_LOOPBACK?JNI_TRUE:JNI_FALSE),lname,ldesc,mac,addresses);
(*env)->SetObjectArrayElement(env,devices,i++,device);
DeleteLocalRef(device);
DeleteLocalRef(mac);
}
/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
(*env)->ExceptionDescribe(env);
return devices;
}
/**
Open Device for Live Capture
**/
JNIEXPORT jstring JNICALL
Java_jpcap_JpcapCaptor_nativeOpenLive(JNIEnv *env,jobject obj,jstring device,jint snaplen,
jint promisc,jint to_ms)
{
char *dev;
jint id;
set_Java_env(env);
id=getJpcapID(env,obj);
if(pcds[id]!=NULL){
return NewString("Another Jpcap instance is being used.");
}
jni_envs[id]=env;
if(device==NULL){
return NewString("Please specify device name.");
}
dev=(char *)GetStringChars(device);
pcds[id]=pcap_open_live(dev,snaplen,promisc,to_ms,pcap_errbuf[id]);
if(pcap_lookupnet(dev,&netnums[id],&netmasks[id],pcap_errbuf[id])==-1){
netmasks[id] = 0;
}
ReleaseStringChars(device,dev);
if(pcds[id]==NULL) return NewString(pcap_errbuf[id]);
//set_info(env,obj,pcds[id]);
linktypes[id]=pcap_datalink(pcds[id]);
return NULL;
}
/**
Open Dumped File
**/
JNIEXPORT jstring JNICALL
Java_jpcap_JpcapCaptor_nativeOpenOffline(JNIEnv *env,jobject obj,jstring filename)
{
char *file;
jint id;
set_Java_env(env);
id=getJpcapID(env,obj);
if(pcds[id]!=NULL){
return NewString("Another Jpcap instance is being used.");
}
jni_envs[id]=env;
file=(char *)GetStringChars(filename);
pcds[id]=pcap_open_offline(file,pcap_errbuf[id]);
ReleaseStringChars(filename,file);
if(pcds[id]==NULL) return NewString(pcap_errbuf[id]);
//set_info(env,obj,pcds[id]);
linktypes[id]=pcap_datalink(pcds[id]);
set_Java_env(env);
return NULL;
}
/**
Close Live Capture Device
**/
JNIEXPORT void JNICALL
Java_jpcap_JpcapCaptor_nativeClose(JNIEnv *env,jobject obj)
{
int id=getJpcapID(env,obj);
if(pcds[id]!=NULL) pcap_close(pcds[id]);
pcds[id]=NULL;
}
/**
Process Packets
**/
JNIEXPORT jint JNICALL
Java_jpcap_JpcapCaptor_processPacket(JNIEnv *env,jobject obj,
jint cnt,jobject handler)
{
jint pkt_cnt;
jint id=getJpcapID(env,obj);
jni_envs[id]=env;
// printf("%d\n",id);
jpcap_handlers[id]=(*env)->NewGlobalRef(env,handler);
pkt_cnt=pcap_dispatch(pcds[id],cnt,dispatcher_handler,(u_char *)id);
(*env)->DeleteGlobalRef(env,jpcap_handlers[id]);
return pkt_cnt;
}
/**
Loop Packets
**/
JNIEXPORT jint JNICALL
Java_jpcap_JpcapCaptor_loopPacket(JNIEnv *env,jobject obj,
jint cnt,jobject handler)
{
jint pkt_cnt;
jint id=getJpcapID(env,obj);
jni_envs[id]=env;
jpcap_handlers[id]=(*env)->NewGlobalRef(env,handler);
pkt_cnt=pcap_loop(pcds[id],cnt,dispatcher_handler,(u_char *)id);
(*env)->DeleteGlobalRef(env,jpcap_handlers[id]);
return pkt_cnt;
}
/**
Get One Packet
**/
JNIEXPORT jobject JNICALL
Java_jpcap_JpcapCaptor_getPacket(JNIEnv *env,jobject obj)
{
struct pcap_pkthdr header;
jobject packet;
int id=getJpcapID(env,obj);
u_char *data=(u_char *)pcap_next(pcds[id],&header);
jni_envs[id]=env;
if(data==NULL) return NULL;
get_packet(header,data,&packet,id);
return packet;
}
/*
* Class: jpcap_JpcapCaptor
* Method: dispatchPacket
* Signature: (ILjpcap/PacketReceiver;)I
*/
JNIEXPORT jint JNICALL Java_jpcap_JpcapCaptor_dispatchPacket
(JNIEnv *env,jobject obj, jint cnt,jobject handler)
{
jint pkt_cnt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -