📄 jpcap.c
字号:
jint id=getJpcapID(env,obj);
jni_envs[id]=env;
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;
}
/*
* Class: jpcap_JpcapCaptor
* Method: setNonBlockingMode
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_jpcap_JpcapCaptor_setNonBlockingMode
(JNIEnv *env, jobject obj, jboolean non_blocking){
jint id=getJpcapID(env,obj);
pcap_setnonblock(pcds[id],non_blocking,pcap_errbuf[id]);
}
/*
* Class: jpcap_JpcapCaptor
* Method: isNonBlockinMode
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_jpcap_JpcapCaptor_isNonBlockinMode
(JNIEnv *env, jobject obj){
jint id=getJpcapID(env,obj);
int nonblocking=pcap_getnonblock(pcds[id],pcap_errbuf[id]);
return (nonblocking!=0?JNI_TRUE:JNI_FALSE);
}
/**
Set Filter
**/
JNIEXPORT void JNICALL
Java_jpcap_JpcapCaptor_setFilter(JNIEnv *env,jobject obj,jstring condition,
jboolean opt)
{
char *cdt=(char *)GetStringChars(condition);
struct bpf_program program;
int id=getJpcapID(env,obj);
char *err=NULL;
if(pcap_compile(pcds[id],&program,cdt,(opt==JNI_TRUE?-1:0),netmasks[id])!=0){
err = pcap_geterr(pcds[id]);
if (err == NULL)
err = "pcap_compile failed";
} else if(pcap_setfilter(pcds[id],&program)!=0){
err = pcap_geterr(pcds[id]);
if (err == NULL)
err = "pcap_setfilter failed";
}
ReleaseStringChars(condition,cdt);
if (err != NULL) {
char buf[2048];
strcpy(buf, "Error occurred while compiling or setting filter: ");
strncat(buf, err, 2047-strlen(buf));
buf[2047] = 0;
Throw(IOException, buf);
}
}
/**
Break loop
**/
JNIEXPORT void JNICALL Java_jpcap_JpcapCaptor_breakLoop
(JNIEnv *env, jobject obj)
{
int id=getJpcapID(env,obj);
pcap_breakloop(pcds[id]);
}
/**
Update Statistics
**/
JNIEXPORT void JNICALL
Java_jpcap_JpcapCaptor_updateStat(JNIEnv *env,jobject obj)
{
struct pcap_stat stat;
jfieldID fid;
int id=getJpcapID(env,obj);
pcap_stats(pcds[id],&stat);
fid=(*env)->GetFieldID(env,Jpcap,"received_packets","I");
(*env)->SetIntField(env,obj,fid,(jint)stat.ps_recv);
fid=(*env)->GetFieldID(env,Jpcap,"dropped_packets","I");
(*env)->SetIntField(env,obj,fid,(jint)stat.ps_drop);
}
/**
Get Error Message
**/
JNIEXPORT jstring JNICALL
Java_jpcap_JpcapCaptor_getErrorMessage(JNIEnv *env,jobject obj)
{
int id=getJpcapID(env,obj);
return NewString(pcap_errbuf[id]);
}
/**
Set Packet Read Timeout (UNIX only)
**/
JNIEXPORT jboolean JNICALL Java_jpcap_JpcapCaptor_setPacketReadTimeout
(JNIEnv *env, jobject obj, jint millis)
{
jboolean success = JNI_FALSE;
#ifndef WIN32
jint id = getJpcapID(env, obj);
int fd = pcap_fileno(pcds[id]);
int s;
struct timeval tv;
tv.tv_usec = (millis % 1000) * 1000;
tv.tv_sec = millis / 1000;
s = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval));
success = (s==0?JNI_TRUE:JNI_FALSE);
#endif
return success;
}
/**
Get Packet Read Timeout (UNIX only)
**/
JNIEXPORT jint JNICALL Java_jpcap_JpcapCaptor_getPacketReadTimeout
(JNIEnv *env, jobject obj)
{
jint rval = -1;
#ifndef WIN32
jint id = getJpcapID(env, obj);
int fd = pcap_fileno(pcds[id]);
int s;
struct timeval tv;
socklen_t len = sizeof(struct timeval);
s = getsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, &len);
if (s == 0 && len == sizeof(struct timeval))
{
rval = (tv.tv_usec / 1000) + (tv.tv_sec * 1000);
}
#endif
return rval;
}
void dispatcher_handler(u_char *id,const struct pcap_pkthdr *header,
const u_char *data)
{
jobject packet;
int ID=(int)id;
JNIEnv *env=jni_envs[ID];
// printf("enter:%d\n",ID);
get_packet(*header,(u_char *)data,&packet,ID);
// printf("got packet:%d\n",ID);
(*env)->CallVoidMethod(env,jpcap_handlers[ID],handleMID,packet);
DeleteLocalRef(packet);
// printf("leave:%d\n",ID);
YIELD();
}
void get_packet(struct pcap_pkthdr header,u_char *data,jobject *packet,int id){
u_short nproto,tproto;
u_short clen=header.caplen,hlen;
u_char *orig_data=data;
JNIEnv *env=jni_envs[id];
// Analyze network protocol
// patch from Kenta
switch(linktypes[id]){
case DLT_RAW:
// based on the hack for Raw IP
nproto=ETHERTYPE_IP;
clen-=datalink_hlen(id);
break;
case DLT_IEEE802:
case DLT_EN10MB:
nproto=get_network_type(data,id);
clen-=datalink_hlen(id);
break;
default:
// get_network_type() macro does NOT work for non-ether packets
// and can cause crash
nproto=UNKNOWN_PROTO;
break;
}
//printf("detect:%d\n",nproto);
if(clen>0){
switch(nproto){
case ETHERTYPE_IP:
clen-=((struct ip *)skip_datalink_header(data,id))->ip_hl<<2;
if(clen>0 &&
!(ntohs(((struct ip *)skip_datalink_header(data,id))->ip_off)&IP_OFFMASK))
tproto=((struct ip *)skip_datalink_header(data,id))->ip_p;
else
tproto=ETHERTYPE_IP;
break;
#ifdef INET6
case ETHERTYPE_IPV6:
clen-=40;
if(clen>0){
u_char *dp=skip_datalink_header(data,id);
struct ip6_ext *ip6_ext;
tproto=((struct ip6_hdr *)dp)->ip6_nxt;
while((tproto==IPPROTO_HOPOPTS || tproto==IPPROTO_DSTOPTS ||
tproto==IPPROTO_ROUTING || tproto==IPPROTO_AH ||
tproto==IPPROTO_FRAGMENT) && clen>0){
switch(tproto){
case IPPROTO_HOPOPTS: /* Hop-by-Hop option */
case IPPROTO_DSTOPTS: /* Destination option */
case IPPROTO_ROUTING: /* Routing option */
case IPPROTO_AH: /* AH option */
ip6_ext=(struct ip6_ext *)dp;
tproto=ip6_ext->ip6e_nxt;
dp+=ip6_ext->ip6e_len;
clen-=ip6_ext->ip6e_len;
break;
case IPPROTO_FRAGMENT: /* Fragment option */
ip6_ext=(struct ip6_ext *)dp;
tproto=ip6_ext->ip6e_nxt;
dp+=16;
clen-=16;
break;
}
if(tproto==IPPROTO_ESP || tproto==IPPROTO_NONE)
tproto=-1;
}
}
break;
#endif
case ETHERTYPE_ARP:
/** XXX - assume that ARP is for Ethernet<->IPv4 **/
clen-=28;
if(clen>0) tproto=ETHERTYPE_ARP;
break;
case UNKNOWN_PROTO: //patch from Kenta
tproto = UNKNOWN_PROTO;
break;
default:
tproto=get_network_type(data,id);
}
}
/** Check for truncated packet */
if((tproto==IPPROTO_TCP && clen<TCPHDRLEN) ||
(tproto==IPPROTO_UDP && clen<UDPHDRLEN) ||
(tproto==IPPROTO_ICMP && clen<ICMPHDRLEN)){
tproto=-1;
}
//printf("create:%d\n",tproto);
/** Create packet object **/
switch(tproto){
case IPPROTO_TCP:
*packet=AllocObject(TCPPacket);break;
case IPPROTO_UDP:
*packet=AllocObject(UDPPacket);break;
case IPPROTO_ICMP:
*packet=AllocObject(ICMPPacket);break;
default:
switch(nproto){
case ETHERTYPE_IP:
*packet=AllocObject(IPPacket);break;
#ifdef INET6
case ETHERTYPE_IPV6:
*packet=AllocObject(IPPacket);break;
#endif
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
*packet=AllocObject(ARPPacket);break;
default:
*packet=AllocObject(Packet);break;
}
}
(*env)->CallVoidMethod(env,*packet,setPacketValueMID,
(jlong)header.ts.tv_sec,(jlong)header.ts.tv_usec,
(jint)header.caplen,(jint)header.len);
//printf("datalink:%d\n",linktypes[id]);
/** Analyze Datalink**/
{
jobject dlpacket=analyze_datalink(env,data,linktypes[id]);
(*env)->CallVoidMethod(env,*packet,setDatalinkPacketMID,dlpacket);
DeleteLocalRef(dlpacket);
}
//printf("network:%d\n",nproto);
/** Analyze Network**/
if(nproto != UNKNOWN_PROTO)
data=skip_datalink_header(data,id);
switch(nproto){
case ETHERTYPE_IP:
clen=ntohs(((struct ip *)data)->ip_len);
hlen=analyze_ip(env,*packet,data);
break;
#ifdef INET6
case ETHERTYPE_IPV6:
clen=ntohs(((struct ip6_hdr *)data)->ip6_plen);
clen+=40;
hlen=analyze_ipv6(env,*packet,data);break;
#endif
case ETHERTYPE_ARP:
clen=hlen=analyze_arp(env,*packet,data);break;
case UNKNOWN_PROTO:
clen=header.caplen;
hlen=0;
break;
default:
clen=header.caplen-datalink_hlen(id);
hlen=0;
break;
}
if(nproto != UNKNOWN_PROTO &&
tproto != UNKNOWN_PROTO &&
clen>header.caplen-datalink_hlen(id))
clen=header.caplen-datalink_hlen(id);
data+=hlen;
clen-=hlen;
//printf("transport:%d\n",tproto);
/** Analyze Transport **/
switch(tproto){
case IPPROTO_TCP:
hlen=analyze_tcp(env,*packet,data); break;
case IPPROTO_UDP:
hlen=UDPHDRLEN;
analyze_udp(env,*packet,data); break;
case IPPROTO_ICMP:
// updated by Damien Daspit 5/14/01
//hlen=clen;
hlen=ICMPHDRLEN;
analyze_icmp(env,*packet,data,clen);break;
default:
{
/*jbyteArray dataArray=(*jni_env)->NewByteArray(jni_env,clen);
(*jni_env)->SetByteArrayRegion(jni_env,dataArray,0,clen,data);
(*jni_env)->CallVoidMethod(jni_env,*packet,setPacketDataMID,dataArray);*/
hlen=0;
break;
}
}
if(hlen>clen) //if the header is cut off
hlen=clen; //cut off hlen
clen-=hlen;
data+=hlen;
hlen=(u_short)(data-orig_data);
//printf("set data: clen=%d, hlen=%d,total=%d/%d\n",clen,hlen,header.len,header.caplen);
{
jbyteArray dataArray=(*env)->NewByteArray(env,hlen);
(*env)->SetByteArrayRegion(env,dataArray,0,hlen,orig_data);
(*env)->CallVoidMethod(env,*packet,setPacketHeaderMID,dataArray);
DeleteLocalRef(dataArray);
if(clen>=0){
dataArray=(*env)->NewByteArray(env,(jsize)clen);
(*env)->SetByteArrayRegion(env,dataArray,0,(jsize)clen,data);
(*env)->CallVoidMethod(env,*packet,setPacketDataMID,dataArray);
DeleteLocalRef(dataArray);
}
}
}
void set_Java_env(JNIEnv *env){
if(Jpcap!=NULL) return;
GlobalClassRef(Jpcap,"jpcap/JpcapCaptor");
GlobalClassRef(JpcapHandler,"jpcap/PacketReceiver");
GlobalClassRef(Packet,"jpcap/packet/Packet");
GlobalClassRef(DatalinkPacket,"jpcap/packet/DatalinkPacket");
GlobalClassRef(EthernetPacket,"jpcap/packet/EthernetPacket");
GlobalClassRef(IPPacket,"jpcap/packet/IPPacket");
GlobalClassRef(TCPPacket,"jpcap/packet/TCPPacket");
GlobalClassRef(UDPPacket,"jpcap/packet/UDPPacket");
GlobalClassRef(ICMPPacket,"jpcap/packet/ICMPPacket");
GlobalClassRef(IPv6Option,"jpcap/packet/IPv6Option");
GlobalClassRef(ARPPacket,"jpcap/packet/ARPPacket");
GlobalClassRef(String,"java/lang/String");
GlobalClassRef(Thread,"java/lang/Thread");
GlobalClassRef(UnknownHostException,"java/net/UnknownHostException");
GlobalClassRef(IOException,"java/io/IOException");
if((*env)->ExceptionCheck(env)==JNI_TRUE){
(*env)->ExceptionDescribe(env);
return;
}
handleMID=(*env)->GetMethodID(env,JpcapHandler,"receivePacket",
"(Ljpcap/packet/Packet;)V");
setPacketValueMID=(*env)->GetMethodID(env,Packet,"setPacketValue",
"(JJII)V");
setDatalinkPacketMID=(*env)->GetMethodID(env,Packet,"setDatalinkPacket",
"(Ljpcap/packet/DatalinkPacket;)V");
setPacketHeaderMID=(*env)->GetMethodID(env,Packet,"setPacketHeader","([B)V");
setPacketDataMID=(*env)->GetMethodID(env,Packet,"setPacketData",
"([B)V");
setEthernetValueMID=(*env)->GetMethodID(env,EthernetPacket,"setValue",
"([B[BS)V");
// updated by Damien Daspit 5/7/01
setIPValueMID=(*env)->GetMethodID(env,IPPacket,"setIPv4Value",
"(BBZZZBZZZSSSSS[B[B)V");
setIPv4OptionMID=(*env)->GetMethodID(env,IPPacket,"setOption","([B)V");
// *******************************
setIPv6ValueMID=(*env)->GetMethodID(env,IPPacket,"setIPv6Value",
"(BBISBS[B[B)V");
addIPv6OptHdrMID=(*env)->GetMethodID(env,IPPacket,"addOptionHeader",
"(Ljpcap/packet/IPv6Option;)V");
// updated by Damien Daspit 5/7/01
setTCPValueMID=(*env)->GetMethodID(env,TCPPacket,"setValue","(IIJJZZZZZZZZIS)V");
// *******************************
setTCPOptionMID=(*env)->GetMethodID(env,TCPPacket,"setOption","([B)V");
setUDPValueMID=(*env)->GetMethodID(env,UDPPacket,"setValue","(III)V");
setICMPValueMID=(*env)->GetMethodID(env,ICMPPacket,"setValue","(BBSSS)V");
setICMPIDMID=(*env)->GetMethodID(env,ICMPPacket,"setID","(SS)V");
setICMPTimestampMID=(*env)->GetMethodID(env,ICMPPacket,"setTimestampValue",
"(III)V");
setICMPRedirectIPMID=(*env)->GetMethodID(env,ICMPPacket,"setRedirectIP",
"([B)V");
getICMPRedirectIPMID=(*env)->GetMethodID(env,ICMPPacket,"getRedirectIP",
"()[B");
setICMPRouterAdMID=(*env)->GetMethodID(env,ICMPPacket,"setRouterAdValue",
"(BBS[Ljava/lang/String;[I)V");
setV6OptValueMID=(*env)->GetMethodID(env,IPv6Option,"setValue",
"(BBB)V");
setV6OptOptionMID=(*env)->GetMethodID(env,IPv6Option,"setOptionData",
"([B)V");
setV6OptRoutingMID=(*env)->GetMethodID(env,IPv6Option,"setRoutingOption",
"(BB[Ljava/lang/String;)V");
setV6OptFragmentMID=(*env)->GetMethodID(env,IPv6Option,"setFragmentOption",
"(SZI)V");
setV6OptAHMID=(*env)->GetMethodID(env,IPv6Option,"setAHOption",
"(II)V");
getSourceAddressMID=(*env)->GetMethodID(env,IPPacket,"getSourceAddress",
"()[B");
getDestinationAddressMID=(*env)->GetMethodID(env,IPPacket,
"getDestinationAddress",
"()[B");
setARPValueMID=(*env)->GetMethodID(env,ARPPacket,"setValue",
"(SSSSS[B[B[B[B)V");
jpcapID=(*env)->GetFieldID(env,Jpcap,"ID","I");
if((*env)->ExceptionCheck(env)==JNI_TRUE){
(*env)->ExceptionDescribe(env);
return;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -