Сканер не работает при выполнении sudo java в Eclipse

Я выполнил эту процедуру, чтобы запускать приложения Java от имени пользователя root, когда это необходимо, из Eclipse (например, я использую 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)

Характеристики:

  • Субунту 15.04
  • Затмение Луна SR2 (4.4.2)
  • Java 8 (Оракул)

person logo_writer    schedule 01.10.2015    source источник


Ответы (1)


Наконец-то мне удалось заставить его работать без использования оболочки для 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

См. это для получения дополнительной информации о поведении Linux при открытии интерфейсов и здесь это полная процедура на тот случай, если вам нужно что-то настроить.

person logo_writer    schedule 10.10.2015