kaitoy / pcap4j

A Java library for capturing, crafting, and sending packets.

Home Page:https://www.pcap4j.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

About the getNextPacketEx problem under linux

gitlei0507 opened this issue · comments

I installed suse linux 15 sp1 in a virtual machine, pcap4j version is 1.8.2, when using getNextPacketEx, it will cause the thread to be stuck and not catch any exception, after testing, I found that assuming detecting 5 IP addresses, it will be stuck when looping to the sixth time, assuming detecting 1 IP address, it will be stuck when looping to the second time. After testing, we found that if we probe 5 IP addresses, the thread will get stuck when the loop reaches the sixth time, and if we probe 1 IP address, it will get stuck when the loop reaches the second time. The code is as follows.

import com.itss.spring.domain.ipc.IpcProbeserverNif;
import com.itss.spring.web.SpringContextUtil;
import com.itss.spring.web.component.pcap.PcapHelper;
import com.itss.spring.web.component.pcap.entity.HostScanInfo;
import com.itss.spring.web.component.pcap.entity.UltraScanInfo;
import com.ursa.acf.util.StringUtils;
import org.pcap4j.core.*;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.EOFException;
import java.net.Inet4Address;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

public class PcapPacketListener {
private static final Logger logger = LoggerFactory.getLogger(PcapPacketListener.class);

private Object lock;

public PcapPacketListener(Object lock) {
    this.lock = lock;
}

public  Map<HostScanInfo, Packet> lisenerForIpScan(UltraScanInfo ultraScanInfo, PcapNetworkInterface nif) throws Exception {
    PcapHelper pcapHelper = (PcapHelper) (SpringContextUtil.getBean(PcapHelper.class));

    
    LinkedHashMap<String, HostScanInfo> incompleteHosts = ultraScanInfo.getIncompleteHosts();
    
    Map<HostScanInfo, Packet> packetTempMap = new HashMap<>();


    String receiveMac = "";
    List<IpcProbeserverNif> receiveNifs = ultraScanInfo.getReceiveNifs();
    for (IpcProbeserverNif receiveNif : receiveNifs) {
        if (receiveNif.getName().equals(nif.getName())) {
            receiveMac = receiveNif.getLinklayeraddress();
            break;
        }
    }
 

    
    PcapHandle.Builder handleBuilder = new PcapHandle.Builder(nif.getName())
            .snaplen(65536)
            .promiscuousMode(PcapNetworkInterface.PromiscuousMode.PROMISCUOUS)
            .timeoutMillis(30)
            .bufferSize(1024 * 1024 * 10);
    
    PcapHandle handler = handleBuilder.build();

    String filter = pcapHelper.createPcapFilter(ultraScanInfo);
    if (!StringUtils.trim(filter).equals("")) {
        handler.setFilter(filter, BpfProgram.BpfCompileMode.OPTIMIZE);
    }

    ExecutorService pool = Executors.newSingleThreadExecutor();
    CloserTask t = new CloserTask(lock);
    Future<Boolean> f = pool.submit(t);


    try {
        int count = 0;
        
        while (!f.isDone()) {
            count++;
         
            logger.error("count:"+count);
            Packet packet =null;
            try {
                packet = handler.getNextPacketEx();
            }catch (PcapNativeException pcapNativeException){
                logger.error("pcapNativeException",pcapNativeException);
            }catch (EOFException eofException){
                logger.error("eofException",eofException);
            }catch (TimeoutException timeoutException){
                logger.error("timeoutException",timeoutException);
            }catch (NotOpenException notOpenException){
                logger.error("notOpenException",notOpenException);
            }
            logger.error("packet is null:"+(packet == null));

            if (packet == null) {
                continue;
            }

            IpV4Packet ipPacket = packet.get(IpV4Packet.class);

            logger.error("ipPacket is null:"+(ipPacket == null));

            if (ipPacket == null) {
                continue;
            }

            Inet4Address srcAddr = ipPacket.getHeader().getSrcAddr();
            String srcAddrIp = srcAddr.getHostAddress();
            logger.error("srcAddrIp:"+srcAddrIp);

            logger.error("incompleteHosts.containsKey(srcAddrIp)"+(incompleteHosts.containsKey(srcAddrIp)));
            if (incompleteHosts.containsKey(srcAddrIp)) {
                HostScanInfo hostScanInfo = new HostScanInfo();
                hostScanInfo.setIp(srcAddrIp);
                hostScanInfo.setReceiveTime(handler.getTimestamp());
                hostScanInfo.setReceiveNifMac(receiveMac);
                packetTempMap.put(hostScanInfo, packet);
            }
            Thread.sleep(10);
        }
    } catch (Exception e) {
        logger.error("循环监听回包出错!", e);
        throw e;
    } finally {
        logger.error("finally start............");
        pool.shutdownNow();
        handler.close();
    }


    // 处理收包
    // if (!packetTempMap.isEmpty()) {
    //     pcapHelper.dealReceivePacket(packetTempMap, ultraScanInfo, handler);
    // }
    // ultraScanInfo.setScanEndTime(new Date());

    return packetTempMap;
}

/**
 * 计时器
 */
private class CloserTask implements Callable<Boolean> {
    private Object lock;

    public CloserTask(Object lock) {
        this.lock = lock;
    }

    @Override
    public Boolean call() throws Exception {
        synchronized (lock) {
            lock.wait();
            return true;
        }
    }
}

}