我已经关注this procedure以便在需要时以root身份运行Java应用程序(因为我使用Xubuntu,例如,当使用jnetpcap
来捕获和分析数据包时)。我遇到的问题是,从Scanner
读取的任何System.in
语句都会失败并提供非常模糊的信息。否则,程序运行正常。
我将附上使用的代码(示例jnetpcap
提供的修改)。在编译这个没有IDE时,它运行正常。
测试代码:
package pruebas;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.PcapBpfProgram;
public class Captura {
private static Scanner sc;
/**
* Main startup method
*
* @param args
* ignored
*/
private static String asString(final byte[] mac) {
final StringBuilder buf = new StringBuilder();
for (byte b : mac) {
if (buf.length() != 0) buf.append(':');
if (b >= 0 && b < 16) buf.append('0');
buf.append(Integer.toHexString((b < 0) ? b + 256 : b).toUpperCase());
}
return buf.toString();
}
private static int readInteger(String msg) {
int ans = 0;
boolean validInput = false;
while (!validInput) {
System.out.print(msg);
String buf = sc.nextLine();
try {
ans = Integer.parseInt(buf.trim());
validInput = true;
}
catch(NumberFormatException nfe) {
validInput = false;
System.out.println("Sorry, this input is incorrect! Please try again.");
}
}
return ans;
}
public static void main(String[] args) {
List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
StringBuilder errbuf = new StringBuilder(); // For any error msgs
/***************************************************************************
* First get a list of devices on this system
**************************************************************************/
int r = Pcap.findAllDevs(alldevs, errbuf);
if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
System.err.printf("Can't read list of devices, error is %s", errbuf.toString());
return;
}
System.out.println("Network devices found:");
int i = 0;
try {
for (PcapIf device : alldevs) {
String description = (device.getDescription() != null) ? device.getDescription() : "No description available";
final byte[] mac = device.getHardwareAddress();
String dir_mac = (mac == null) ? "No MAC address associated" : asString(mac);
System.out.printf("#%d: %s [%s] MAC:[%s]\n", i++, device.getName(), description, dir_mac);
}// for
sc = new Scanner(System.in);
int opc = readInteger("\nSelect device [0-" + (alldevs.size() - 1) + "]:\t");
PcapIf device = alldevs.get(opc); // We know we have at least 1 device
System.out.printf("\nChoosing '%s' on your behalf:\n", (device
.getDescription() != null) ? device.getDescription()
: device.getName());
/***************************************************************************
* Second we open up the selected device
**************************************************************************/
/*
* "snaplen" is short for 'snapshot length', as it refers to the
* amount of actual data captured from each packet passing through
* the specified network interface. 64*1024 = 65536 bytes; campo len
* en Ethernet(16 bits) tam máx de trama
*/
int snaplen = 64 * 1024; // Capture all packets, no trucation
int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
int timeout = 10 * 1000; // 10 seconds in millis
Pcap pcap = Pcap.openLive(device.getName(), snaplen, flags,
timeout, errbuf);
if (pcap == null) {
System.err.printf("Error while opening device for capture: "
+ errbuf.toString());
return;
}// if
/******** F I L T R O ********/
PcapBpfProgram filter = new PcapBpfProgram();
String expression = ""; // "port 80";
int optimize = 0; // 1 means true, 0 means false
int netmask = 0;
int r2 = pcap.compile(filter, expression, optimize, netmask);
if (r2 != Pcap.OK) {
System.out.println("Filter error: " + pcap.getErr());
}// if
pcap.setFilter(filter);
/****************/
/***************************************************************************
* Third we create a packet handler which will receive packets from
* the libpcap loop.
**********************************************************************/
PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {
public void nextPacket(PcapPacket packet, String user) {
System.out.printf(
"Received packet at %s caplen=%-4d len=%-4d %s\n",
new Date(packet.getCaptureHeader()
.timestampInMillis()), packet
.getCaptureHeader().caplen(), // Length actually captured
packet.getCaptureHeader().wirelen(), // Original length
user // User supplied object
);
/****** Desencapsulado ********/
for (int i = 0; i < packet.size(); i++) {
System.out.printf("%02X ", packet.getUByte(i));
if (i % 16 == 15)
System.out.println("");
}
System.out.println("\n\nHeader: " + packet.toHexdump());
}
};
/***************************************************************************
* Fourth we enter the loop and tell it to capture 10 packets. The
* loop method does a mapping of pcap.datalink() DLT value to
* JProtocol ID, which is needed by JScanner. The scanner scans the
* packet buffer and decodes the headers. The mapping is done
* automatically, although a variation on the loop method exists
* that allows the programmer to sepecify exactly which protocol ID
* to use as the data link type for this pcap interface.
**************************************************************************/
pcap.loop(10, jpacketHandler, "jNetPcap rocks!");
/***************************************************************************
* Last thing to do is close the pcap handle
**************************************************************************/
pcap.close();
sc.close();
} catch (IOException e) {
System.out.println(":'(");
//e.printStackTrace();
}
}
}
输出:
Select device [0-14]: at java.util.Scanner.nextLine(Scanner.java:1540)
at pruebas.Captura.readInteger(Captura.java:50)
at pruebas.Captura.main(Captura.java:88)
功能
答案 0 :(得分:0)
我终于设法让它工作而不使用java
的包装器。它与Linux中的文件系统功能有关。
要让java
列出并选择网络接口,以及分析和捕获数据包,请转到IDE使用的可执行文件所在的目录(例如,/usr/lib/jvm/java-8-oracle/bin
;在Eclipse中,您可以获得它通过查看控制台标题栏)并在之前运行以下命令:
sudo setcap cap_net_raw,cap_net_admin=eip java
然后运行您的项目。 一旦您测试了项目,请运行以下命令以保留以前的内容:
sudo setcap -r java
您可以通过运行来查看是否已应用/删除了功能:
getcap java